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     */
081    public class WindItemRenderer extends AbstractXYItemRenderer
082            implements XYItemRenderer, Cloneable, PublicCloneable, Serializable {
083    
084        /** For serialization. */
085        private static final long serialVersionUID = 8078914101916976844L;
086    
087        /**
088         * Creates a new renderer.
089         */
090        public WindItemRenderer() {
091            super();
092        }
093    
094        /**
095         * Draws the visual representation of a single data item.
096         *
097         * @param g2  the graphics device.
098         * @param state  the renderer state.
099         * @param plotArea  the area within which the plot is being drawn.
100         * @param info  optional information collection.
101         * @param plot  the plot (can be used to obtain standard color
102         *              information etc).
103         * @param domainAxis  the horizontal axis.
104         * @param rangeAxis  the vertical axis.
105         * @param dataset  the dataset.
106         * @param series  the series index (zero-based).
107         * @param item  the item index (zero-based).
108         * @param crosshairState  crosshair information for the plot
109         *                        (<code>null</code> permitted).
110         * @param pass  the pass index.
111         */
112        public void drawItem(Graphics2D g2,
113                             XYItemRendererState state,
114                             Rectangle2D plotArea,
115                             PlotRenderingInfo info,
116                             XYPlot plot,
117                             ValueAxis domainAxis,
118                             ValueAxis rangeAxis,
119                             XYDataset dataset,
120                             int series,
121                             int item,
122                             CrosshairState crosshairState,
123                             int pass) {
124    
125            WindDataset windData = (WindDataset) dataset;
126    
127            Paint seriesPaint = getItemPaint(series, item);
128            Stroke seriesStroke = getItemStroke(series, item);
129            g2.setPaint(seriesPaint);
130            g2.setStroke(seriesStroke);
131    
132            // get the data point...
133    
134            Number x = windData.getX(series, item);
135            Number windDir = windData.getWindDirection(series, item);
136            Number wforce = windData.getWindForce(series, item);
137            double windForce = wforce.doubleValue();
138    
139            double wdirt = Math.toRadians(windDir.doubleValue() * (-30.0) - 90.0);
140    
141            double ax1, ax2, ay1, ay2, rax2, ray2;
142    
143            RectangleEdge domainAxisLocation = plot.getDomainAxisEdge();
144            RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
145            ax1 = domainAxis.valueToJava2D(x.doubleValue(), plotArea,
146                    domainAxisLocation);
147            ay1 = rangeAxis.valueToJava2D(0.0, plotArea, rangeAxisLocation);
148    
149            rax2 = x.doubleValue() + (windForce * Math.cos(wdirt) * 8000000.0);
150            ray2 = windForce * Math.sin(wdirt);
151    
152            ax2 = domainAxis.valueToJava2D(rax2, plotArea, domainAxisLocation);
153            ay2 = rangeAxis.valueToJava2D(ray2, plotArea, rangeAxisLocation);
154    
155            int diri = windDir.intValue();
156            int forcei = wforce.intValue();
157            String dirforce = diri + "-" + forcei;
158            Line2D line = new Line2D.Double(ax1, ay1, ax2, ay2);
159    
160            g2.draw(line);
161            g2.setPaint(Color.blue);
162            g2.setFont(new Font("foo", 1, 9));
163    
164            g2.drawString(dirforce, (float) ax1, (float) ay1);
165    
166            g2.setPaint(seriesPaint);
167            g2.setStroke(seriesStroke);
168    
169            double alx2, aly2, arx2, ary2;
170            double ralx2, raly2, rarx2, rary2;
171    
172            double aldir = Math.toRadians(windDir.doubleValue()
173                    * (-30.0) - 90.0 - 5.0);
174            ralx2 = wforce.doubleValue() * Math.cos(aldir) * 8000000 * 0.8
175            + x.doubleValue();
176            raly2 = wforce.doubleValue() * Math.sin(aldir) * 0.8;
177    
178            alx2 = domainAxis.valueToJava2D(ralx2, plotArea, domainAxisLocation);
179            aly2 = rangeAxis.valueToJava2D(raly2, plotArea, rangeAxisLocation);
180    
181            line = new Line2D.Double(alx2, aly2, ax2, ay2);
182            g2.draw(line);
183    
184            double ardir = Math.toRadians(windDir.doubleValue()
185                    * (-30.0) - 90.0 + 5.0);
186            rarx2 = wforce.doubleValue() * Math.cos(ardir) * 8000000 * 0.8
187                    + x.doubleValue();
188            rary2 = wforce.doubleValue() * Math.sin(ardir) * 0.8;
189    
190            arx2 = domainAxis.valueToJava2D(rarx2, plotArea, domainAxisLocation);
191            ary2 = rangeAxis.valueToJava2D(rary2, plotArea, rangeAxisLocation);
192    
193            line = new Line2D.Double(arx2, ary2, ax2, ay2);
194            g2.draw(line);
195    
196        }
197    
198        /**
199         * Returns a clone of the renderer.
200         *
201         * @return A clone.
202         *
203         * @throws CloneNotSupportedException  if the renderer cannot be cloned.
204         */
205        public Object clone() throws CloneNotSupportedException {
206            return super.clone();
207        }
208    
209    }