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