Source Code Cross Referenced for XYDifferenceRenderer.java in  » Chart » jfreechart » org » jfree » chart » renderer » xy » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Chart » jfreechart » org.jfree.chart.renderer.xy 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* ===========================================================
0002:         * JFreeChart : a free chart library for the Java(tm) platform
0003:         * ===========================================================
0004:         *
0005:         * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
0006:         *
0007:         * Project Info:  http://www.jfree.org/jfreechart/index.html
0008:         *
0009:         * This library is free software; you can redistribute it and/or modify it 
0010:         * under the terms of the GNU Lesser General Public License as published by 
0011:         * the Free Software Foundation; either version 2.1 of the License, or 
0012:         * (at your option) any later version.
0013:         *
0014:         * This library is distributed in the hope that it will be useful, but 
0015:         * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
0016:         * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
0017:         * License for more details.
0018:         *
0019:         * You should have received a copy of the GNU Lesser General Public
0020:         * License along with this library; if not, write to the Free Software
0021:         * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
0022:         * USA.  
0023:         *
0024:         * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
0025:         * in the United States and other countries.]
0026:         *
0027:         * -------------------------
0028:         * XYDifferenceRenderer.java
0029:         * -------------------------
0030:         * (C) Copyright 2003-2007, by Object Refinery Limited and Contributors.
0031:         *
0032:         * Original Author:  David Gilbert (for Object Refinery Limited);
0033:         * Contributor(s):   Richard West, Advanced Micro Devices, Inc. (major rewrite 
0034:         *                   of difference drawing algorithm);
0035:         *
0036:         * $Id: XYDifferenceRenderer.java,v 1.12.2.15 2007/05/18 10:28:31 mungady Exp $
0037:         *
0038:         * Changes:
0039:         * --------
0040:         * 30-Apr-2003 : Version 1 (DG);
0041:         * 30-Jul-2003 : Modified entity constructor (CZ);
0042:         * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
0043:         * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
0044:         * 09-Feb-2004 : Updated to support horizontal plot orientation (DG);
0045:         * 10-Feb-2004 : Added default constructor, setter methods and updated 
0046:         *               Javadocs (DG);
0047:         * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState (DG);
0048:         * 30-Mar-2004 : Fixed bug in getNegativePaint() method (DG);
0049:         * 15-Jul-2004 : Switched getX() with getXValue() and getY() with 
0050:         *               getYValue() (DG);
0051:         * 25-Aug-2004 : Fixed a bug preventing the use of crosshairs (DG);
0052:         * 11-Nov-2004 : Now uses ShapeUtilities to translate shapes (DG);
0053:         * 19-Jan-2005 : Now accesses only primitive values from dataset (DG);
0054:         * 22-Feb-2005 : Override getLegendItem(int, int) to return "line" items (DG);
0055:         * 13-Apr-2005 : Fixed shape positioning bug (id = 1182062) (DG);
0056:         * 20-Apr-2005 : Use generators for legend tooltips and URLs (DG);
0057:         * 04-May-2005 : Override equals() method, renamed get/setPlotShapes() -->
0058:         *               get/setShapesVisible (DG);
0059:         * 09-Jun-2005 : Updated equals() to handle GradientPaint (DG);
0060:         * 16-Jun-2005 : Fix bug (1221021) affecting stroke used for each series (DG);
0061:         * ------------- JFREECHART 1.0.x ---------------------------------------------
0062:         * 24-Jan-2007 : Added flag to allow rounding of x-coordinates, and fixed
0063:         *               bug in clone() (DG);
0064:         * 05-Feb-2007 : Added an extra call to updateCrosshairValues() in 
0065:         *               drawItemPass1(), to fix bug 1564967 (DG);
0066:         * 06-Feb-2007 : Fixed bug 1086307, crosshairs with multiple axes (DG);
0067:         * 08-Mar-2007 : Fixed entity generation (DG);
0068:         * 20-Apr-2007 : Updated getLegendItem() for renderer change (DG);
0069:         * 23-Apr-2007 : Rewrite of difference drawing algorithm to allow use of 
0070:         *               series with disjoint x-values (RW);
0071:         * 04-May-2007 : Set processVisibleItemsOnly flag to false (DG);
0072:         * 17-May-2007 : Set datasetIndex and seriesIndex in getLegendItem() (DG);
0073:         * 18-May-2007 : Set dataset and seriesKey for LegendItem (DG);
0074:         * 
0075:         */
0076:
0077:        package org.jfree.chart.renderer.xy;
0078:
0079:        import java.awt.Color;
0080:        import java.awt.Graphics2D;
0081:        import java.awt.Paint;
0082:        import java.awt.Shape;
0083:        import java.awt.Stroke;
0084:        import java.awt.geom.GeneralPath;
0085:        import java.awt.geom.Line2D;
0086:        import java.awt.geom.Rectangle2D;
0087:        import java.io.IOException;
0088:        import java.io.ObjectInputStream;
0089:        import java.io.ObjectOutputStream;
0090:        import java.io.Serializable;
0091:        import java.util.Collections;
0092:        import java.util.LinkedList;
0093:
0094:        import org.jfree.chart.LegendItem;
0095:        import org.jfree.chart.axis.ValueAxis;
0096:        import org.jfree.chart.entity.EntityCollection;
0097:        import org.jfree.chart.entity.XYItemEntity;
0098:        import org.jfree.chart.event.RendererChangeEvent;
0099:        import org.jfree.chart.labels.XYToolTipGenerator;
0100:        import org.jfree.chart.plot.CrosshairState;
0101:        import org.jfree.chart.plot.PlotOrientation;
0102:        import org.jfree.chart.plot.PlotRenderingInfo;
0103:        import org.jfree.chart.plot.XYPlot;
0104:        import org.jfree.chart.urls.XYURLGenerator;
0105:        import org.jfree.data.xy.XYDataset;
0106:        import org.jfree.io.SerialUtilities;
0107:        import org.jfree.ui.RectangleEdge;
0108:        import org.jfree.util.PaintUtilities;
0109:        import org.jfree.util.PublicCloneable;
0110:        import org.jfree.util.ShapeUtilities;
0111:
0112:        /**
0113:         * A renderer for an {@link XYPlot} that highlights the differences between two
0114:         * series.
0115:         */
0116:        public class XYDifferenceRenderer extends AbstractXYItemRenderer
0117:                implements  XYItemRenderer, Cloneable, PublicCloneable,
0118:                Serializable {
0119:
0120:            /** For serialization. */
0121:            private static final long serialVersionUID = -8447915602375584857L;
0122:
0123:            /** The paint used to highlight positive differences (y(0) > y(1)). */
0124:            private transient Paint positivePaint;
0125:
0126:            /** The paint used to highlight negative differences (y(0) < y(1)). */
0127:            private transient Paint negativePaint;
0128:
0129:            /** Display shapes at each point? */
0130:            private boolean shapesVisible;
0131:
0132:            /** The shape to display in the legend item. */
0133:            private transient Shape legendLine;
0134:
0135:            /**
0136:             * This flag controls whether or not the x-coordinates (in Java2D space) 
0137:             * are rounded to integers.  When set to true, this can avoid the vertical
0138:             * striping that anti-aliasing can generate.  However, the rounding may not
0139:             * be appropriate for output in high resolution formats (for example, 
0140:             * vector graphics formats such as SVG and PDF).
0141:             * 
0142:             * @since 1.0.4
0143:             */
0144:            private boolean roundXCoordinates;
0145:
0146:            /**
0147:             * Creates a new renderer with default attributes.
0148:             */
0149:            public XYDifferenceRenderer() {
0150:                this (Color.green, Color.red, false);
0151:            }
0152:
0153:            /**
0154:             * Creates a new renderer.
0155:             *
0156:             * @param positivePaint  the highlight color for positive differences 
0157:             *                       (<code>null</code> not permitted).
0158:             * @param negativePaint  the highlight color for negative differences 
0159:             *                       (<code>null</code> not permitted).
0160:             * @param shapes  draw shapes?
0161:             */
0162:            public XYDifferenceRenderer(Paint positivePaint,
0163:                    Paint negativePaint, boolean shapes) {
0164:                if (positivePaint == null) {
0165:                    throw new IllegalArgumentException(
0166:                            "Null 'positivePaint' argument.");
0167:                }
0168:                if (negativePaint == null) {
0169:                    throw new IllegalArgumentException(
0170:                            "Null 'negativePaint' argument.");
0171:                }
0172:                this .positivePaint = positivePaint;
0173:                this .negativePaint = negativePaint;
0174:                this .shapesVisible = shapes;
0175:                this .legendLine = new Line2D.Double(-7.0, 0.0, 7.0, 0.0);
0176:                this .roundXCoordinates = false;
0177:            }
0178:
0179:            /**
0180:             * Returns the paint used to highlight positive differences.
0181:             *
0182:             * @return The paint (never <code>null</code>).
0183:             * 
0184:             * @see #setPositivePaint(Paint)
0185:             */
0186:            public Paint getPositivePaint() {
0187:                return this .positivePaint;
0188:            }
0189:
0190:            /**
0191:             * Sets the paint used to highlight positive differences.
0192:             * 
0193:             * @param paint  the paint (<code>null</code> not permitted).
0194:             * 
0195:             * @see #getPositivePaint()
0196:             */
0197:            public void setPositivePaint(Paint paint) {
0198:                if (paint == null) {
0199:                    throw new IllegalArgumentException("Null 'paint' argument.");
0200:                }
0201:                this .positivePaint = paint;
0202:                notifyListeners(new RendererChangeEvent(this ));
0203:            }
0204:
0205:            /**
0206:             * Returns the paint used to highlight negative differences.
0207:             *
0208:             * @return The paint (never <code>null</code>).
0209:             * 
0210:             * @see #setNegativePaint(Paint)
0211:             */
0212:            public Paint getNegativePaint() {
0213:                return this .negativePaint;
0214:            }
0215:
0216:            /**
0217:             * Sets the paint used to highlight negative differences.
0218:             * 
0219:             * @param paint  the paint (<code>null</code> not permitted).
0220:             * 
0221:             * @see #getNegativePaint()
0222:             */
0223:            public void setNegativePaint(Paint paint) {
0224:                if (paint == null) {
0225:                    throw new IllegalArgumentException("Null 'paint' argument.");
0226:                }
0227:                this .negativePaint = paint;
0228:                notifyListeners(new RendererChangeEvent(this ));
0229:            }
0230:
0231:            /**
0232:             * Returns a flag that controls whether or not shapes are drawn for each 
0233:             * data value.
0234:             * 
0235:             * @return A boolean.
0236:             * 
0237:             * @see #setShapesVisible(boolean)
0238:             */
0239:            public boolean getShapesVisible() {
0240:                return this .shapesVisible;
0241:            }
0242:
0243:            /**
0244:             * Sets a flag that controls whether or not shapes are drawn for each 
0245:             * data value.
0246:             * 
0247:             * @param flag  the flag.
0248:             * 
0249:             * @see #getShapesVisible()
0250:             */
0251:            public void setShapesVisible(boolean flag) {
0252:                this .shapesVisible = flag;
0253:                notifyListeners(new RendererChangeEvent(this ));
0254:            }
0255:
0256:            /**
0257:             * Returns the shape used to represent a line in the legend.
0258:             * 
0259:             * @return The legend line (never <code>null</code>).
0260:             * 
0261:             * @see #setLegendLine(Shape)
0262:             */
0263:            public Shape getLegendLine() {
0264:                return this .legendLine;
0265:            }
0266:
0267:            /**
0268:             * Sets the shape used as a line in each legend item and sends a 
0269:             * {@link RendererChangeEvent} to all registered listeners.
0270:             * 
0271:             * @param line  the line (<code>null</code> not permitted).
0272:             * 
0273:             * @see #getLegendLine()
0274:             */
0275:            public void setLegendLine(Shape line) {
0276:                if (line == null) {
0277:                    throw new IllegalArgumentException("Null 'line' argument.");
0278:                }
0279:                this .legendLine = line;
0280:                notifyListeners(new RendererChangeEvent(this ));
0281:            }
0282:
0283:            /**
0284:             * Returns the flag that controls whether or not the x-coordinates (in
0285:             * Java2D space) are rounded to integer values.
0286:             * 
0287:             * @return The flag.
0288:             * 
0289:             * @since 1.0.4
0290:             * 
0291:             * @see #setRoundXCoordinates(boolean)
0292:             */
0293:            public boolean getRoundXCoordinates() {
0294:                return this .roundXCoordinates;
0295:            }
0296:
0297:            /**
0298:             * Sets the flag that controls whether or not the x-coordinates (in 
0299:             * Java2D space) are rounded to integer values, and sends a 
0300:             * {@link RendererChangeEvent} to all registered listeners.
0301:             * 
0302:             * @param round  the new flag value.
0303:             * 
0304:             * @since 1.0.4
0305:             * 
0306:             * @see #getRoundXCoordinates()
0307:             */
0308:            public void setRoundXCoordinates(boolean round) {
0309:                this .roundXCoordinates = round;
0310:                notifyListeners(new RendererChangeEvent(this ));
0311:            }
0312:
0313:            /**
0314:             * Initialises the renderer and returns a state object that should be 
0315:             * passed to subsequent calls to the drawItem() method.  This method will 
0316:             * be called before the first item is rendered, giving the renderer an 
0317:             * opportunity to initialise any state information it wants to maintain.  
0318:             * The renderer can do nothing if it chooses.
0319:             *
0320:             * @param g2  the graphics device.
0321:             * @param dataArea  the area inside the axes.
0322:             * @param plot  the plot.
0323:             * @param data  the data.
0324:             * @param info  an optional info collection object to return data back to 
0325:             *              the caller.
0326:             *
0327:             * @return A state object.
0328:             */
0329:            public XYItemRendererState initialise(Graphics2D g2,
0330:                    Rectangle2D dataArea, XYPlot plot, XYDataset data,
0331:                    PlotRenderingInfo info) {
0332:
0333:                XYItemRendererState state = super .initialise(g2, dataArea,
0334:                        plot, data, info);
0335:                state.setProcessVisibleItemsOnly(false);
0336:                return state;
0337:
0338:            }
0339:
0340:            /**
0341:             * Returns <code>2</code>, the number of passes required by the renderer.  
0342:             * The {@link XYPlot} will run through the dataset this number of times.
0343:             * 
0344:             * @return The number of passes required by the renderer.
0345:             */
0346:            public int getPassCount() {
0347:                return 2;
0348:            }
0349:
0350:            /**
0351:             * Draws the visual representation of a single data item.
0352:             *
0353:             * @param g2  the graphics device.
0354:             * @param state  the renderer state.
0355:             * @param dataArea  the area within which the data is being drawn.
0356:             * @param info  collects information about the drawing.
0357:             * @param plot  the plot (can be used to obtain standard color 
0358:             *              information etc).
0359:             * @param domainAxis  the domain (horizontal) axis.
0360:             * @param rangeAxis  the range (vertical) axis.
0361:             * @param dataset  the dataset.
0362:             * @param series  the series index (zero-based).
0363:             * @param item  the item index (zero-based).
0364:             * @param crosshairState  crosshair information for the plot 
0365:             *                        (<code>null</code> permitted).
0366:             * @param pass  the pass index.
0367:             */
0368:            public void drawItem(Graphics2D g2, XYItemRendererState state,
0369:                    Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot,
0370:                    ValueAxis domainAxis, ValueAxis rangeAxis,
0371:                    XYDataset dataset, int series, int item,
0372:                    CrosshairState crosshairState, int pass) {
0373:
0374:                if (pass == 0) {
0375:                    drawItemPass0(g2, dataArea, info, plot, domainAxis,
0376:                            rangeAxis, dataset, series, item, crosshairState);
0377:                } else if (pass == 1) {
0378:                    drawItemPass1(g2, dataArea, info, plot, domainAxis,
0379:                            rangeAxis, dataset, series, item, crosshairState);
0380:                }
0381:
0382:            }
0383:
0384:            /**
0385:             * Draws the visual representation of a single data item, first pass.
0386:             *
0387:             * @param x_graphics  the graphics device.
0388:             * @param x_dataArea  the area within which the data is being drawn.
0389:             * @param x_info  collects information about the drawing.
0390:             * @param x_plot  the plot (can be used to obtain standard color 
0391:             *                information etc).
0392:             * @param x_domainAxis  the domain (horizontal) axis.
0393:             * @param x_rangeAxis  the range (vertical) axis.
0394:             * @param x_dataset  the dataset.
0395:             * @param x_series  the series index (zero-based).
0396:             * @param x_item  the item index (zero-based).
0397:             * @param x_crosshairState  crosshair information for the plot 
0398:             *                          (<code>null</code> permitted).
0399:             */
0400:            protected void drawItemPass0(Graphics2D x_graphics,
0401:                    Rectangle2D x_dataArea, PlotRenderingInfo x_info,
0402:                    XYPlot x_plot, ValueAxis x_domainAxis,
0403:                    ValueAxis x_rangeAxis, XYDataset x_dataset, int x_series,
0404:                    int x_item, CrosshairState x_crosshairState) {
0405:
0406:                if (!((0 == x_series) && (0 == x_item))) {
0407:                    return;
0408:                }
0409:
0410:                boolean b_impliedZeroSubtrahend = (1 == x_dataset
0411:                        .getSeriesCount());
0412:
0413:                // check if either series is a degenerate case (i.e. less than 2 points)
0414:                if (isEitherSeriesDegenerate(x_dataset, b_impliedZeroSubtrahend)) {
0415:                    return;
0416:                }
0417:
0418:                // check if series are disjoint (i.e. domain-spans do not overlap)
0419:                if (!b_impliedZeroSubtrahend && areSeriesDisjoint(x_dataset)) {
0420:                    return;
0421:                }
0422:
0423:                // polygon definitions
0424:                LinkedList l_minuendXs = new LinkedList();
0425:                LinkedList l_minuendYs = new LinkedList();
0426:                LinkedList l_subtrahendXs = new LinkedList();
0427:                LinkedList l_subtrahendYs = new LinkedList();
0428:                LinkedList l_polygonXs = new LinkedList();
0429:                LinkedList l_polygonYs = new LinkedList();
0430:
0431:                // state
0432:                int l_minuendItem = 0;
0433:                int l_minuendItemCount = x_dataset.getItemCount(0);
0434:                Double l_minuendCurX = null;
0435:                Double l_minuendNextX = null;
0436:                Double l_minuendCurY = null;
0437:                Double l_minuendNextY = null;
0438:                double l_minuendMaxY = Double.NEGATIVE_INFINITY;
0439:                double l_minuendMinY = Double.POSITIVE_INFINITY;
0440:
0441:                int l_subtrahendItem = 0;
0442:                int l_subtrahendItemCount = 0; // actual value set below
0443:                Double l_subtrahendCurX = null;
0444:                Double l_subtrahendNextX = null;
0445:                Double l_subtrahendCurY = null;
0446:                Double l_subtrahendNextY = null;
0447:                double l_subtrahendMaxY = Double.NEGATIVE_INFINITY;
0448:                double l_subtrahendMinY = Double.POSITIVE_INFINITY;
0449:
0450:                // if a subtrahend is not specified, assume it is zero
0451:                if (b_impliedZeroSubtrahend) {
0452:                    l_subtrahendItem = 0;
0453:                    l_subtrahendItemCount = 2;
0454:                    l_subtrahendCurX = new Double(x_dataset.getXValue(0, 0));
0455:                    l_subtrahendNextX = new Double(x_dataset.getXValue(0,
0456:                            (l_minuendItemCount - 1)));
0457:                    l_subtrahendCurY = new Double(0.0);
0458:                    l_subtrahendNextY = new Double(0.0);
0459:                    l_subtrahendMaxY = 0.0;
0460:                    l_subtrahendMinY = 0.0;
0461:
0462:                    l_subtrahendXs.add(l_subtrahendCurX);
0463:                    l_subtrahendYs.add(l_subtrahendCurY);
0464:                } else {
0465:                    l_subtrahendItemCount = x_dataset.getItemCount(1);
0466:                }
0467:
0468:                boolean b_minuendDone = false;
0469:                boolean b_minuendAdvanced = true;
0470:                boolean b_minuendAtIntersect = false;
0471:                boolean b_minuendFastForward = false;
0472:                boolean b_subtrahendDone = false;
0473:                boolean b_subtrahendAdvanced = true;
0474:                boolean b_subtrahendAtIntersect = false;
0475:                boolean b_subtrahendFastForward = false;
0476:                boolean b_colinear = false;
0477:
0478:                boolean b_positive;
0479:
0480:                // coordinate pairs
0481:                double l_x1 = 0.0, l_y1 = 0.0; // current minuend point
0482:                double l_x2 = 0.0, l_y2 = 0.0; // next minuend point
0483:                double l_x3 = 0.0, l_y3 = 0.0; // current subtrahend point
0484:                double l_x4 = 0.0, l_y4 = 0.0; // next subtrahend point
0485:
0486:                // fast-forward through leading tails
0487:                boolean b_fastForwardDone = false;
0488:                while (!b_fastForwardDone) {
0489:                    // get the x and y coordinates
0490:                    l_x1 = x_dataset.getXValue(0, l_minuendItem);
0491:                    l_y1 = x_dataset.getYValue(0, l_minuendItem);
0492:                    l_x2 = x_dataset.getXValue(0, l_minuendItem + 1);
0493:                    l_y2 = x_dataset.getYValue(0, l_minuendItem + 1);
0494:
0495:                    l_minuendCurX = new Double(l_x1);
0496:                    l_minuendCurY = new Double(l_y1);
0497:                    l_minuendNextX = new Double(l_x2);
0498:                    l_minuendNextY = new Double(l_y2);
0499:
0500:                    if (b_impliedZeroSubtrahend) {
0501:                        l_x3 = l_subtrahendCurX.doubleValue();
0502:                        l_y3 = l_subtrahendCurY.doubleValue();
0503:                        l_x4 = l_subtrahendNextX.doubleValue();
0504:                        l_y4 = l_subtrahendNextY.doubleValue();
0505:                    } else {
0506:                        l_x3 = x_dataset.getXValue(1, l_subtrahendItem);
0507:                        l_y3 = x_dataset.getYValue(1, l_subtrahendItem);
0508:                        l_x4 = x_dataset.getXValue(1, l_subtrahendItem + 1);
0509:                        l_y4 = x_dataset.getYValue(1, l_subtrahendItem + 1);
0510:
0511:                        l_subtrahendCurX = new Double(l_x3);
0512:                        l_subtrahendCurY = new Double(l_y3);
0513:                        l_subtrahendNextX = new Double(l_x4);
0514:                        l_subtrahendNextY = new Double(l_y4);
0515:                    }
0516:
0517:                    if (l_x2 <= l_x3) {
0518:                        // minuend needs to be fast forwarded
0519:                        l_minuendItem++;
0520:                        b_minuendFastForward = true;
0521:                        continue;
0522:                    }
0523:
0524:                    if (l_x4 <= l_x1) {
0525:                        // subtrahend needs to be fast forwarded
0526:                        l_subtrahendItem++;
0527:                        b_subtrahendFastForward = true;
0528:                        continue;
0529:                    }
0530:
0531:                    // check if initial polygon needs to be clipped
0532:                    if ((l_x3 < l_x1) && (l_x1 < l_x4)) {
0533:                        // project onto subtrahend
0534:                        double l_slope = (l_y4 - l_y3) / (l_x4 - l_x3);
0535:                        l_subtrahendCurX = l_minuendCurX;
0536:                        l_subtrahendCurY = new Double((l_slope * l_x1)
0537:                                + (l_y3 - (l_slope * l_x3)));
0538:
0539:                        l_subtrahendXs.add(l_subtrahendCurX);
0540:                        l_subtrahendYs.add(l_subtrahendCurY);
0541:                    }
0542:
0543:                    if ((l_x1 < l_x3) && (l_x3 < l_x2)) {
0544:                        // project onto minuend
0545:                        double l_slope = (l_y2 - l_y1) / (l_x2 - l_x1);
0546:                        l_minuendCurX = l_subtrahendCurX;
0547:                        l_minuendCurY = new Double((l_slope * l_x3)
0548:                                + (l_y1 - (l_slope * l_x1)));
0549:
0550:                        l_minuendXs.add(l_minuendCurX);
0551:                        l_minuendYs.add(l_minuendCurY);
0552:                    }
0553:
0554:                    l_minuendMaxY = l_minuendCurY.doubleValue();
0555:                    l_minuendMinY = l_minuendCurY.doubleValue();
0556:                    l_subtrahendMaxY = l_subtrahendCurY.doubleValue();
0557:                    l_subtrahendMinY = l_subtrahendCurY.doubleValue();
0558:
0559:                    b_fastForwardDone = true;
0560:                }
0561:
0562:                // start of algorithm
0563:                while (!b_minuendDone && !b_subtrahendDone) {
0564:                    if (!b_minuendDone && !b_minuendFastForward
0565:                            && b_minuendAdvanced) {
0566:                        l_x1 = x_dataset.getXValue(0, l_minuendItem);
0567:                        l_y1 = x_dataset.getYValue(0, l_minuendItem);
0568:                        l_minuendCurX = new Double(l_x1);
0569:                        l_minuendCurY = new Double(l_y1);
0570:
0571:                        if (!b_minuendAtIntersect) {
0572:                            l_minuendXs.add(l_minuendCurX);
0573:                            l_minuendYs.add(l_minuendCurY);
0574:                        }
0575:
0576:                        l_minuendMaxY = Math.max(l_minuendMaxY, l_y1);
0577:                        l_minuendMinY = Math.min(l_minuendMinY, l_y1);
0578:
0579:                        l_x2 = x_dataset.getXValue(0, l_minuendItem + 1);
0580:                        l_y2 = x_dataset.getYValue(0, l_minuendItem + 1);
0581:                        l_minuendNextX = new Double(l_x2);
0582:                        l_minuendNextY = new Double(l_y2);
0583:                    }
0584:
0585:                    // never updated the subtrahend if it is implied to be zero
0586:                    if (!b_impliedZeroSubtrahend && !b_subtrahendDone
0587:                            && !b_subtrahendFastForward && b_subtrahendAdvanced) {
0588:                        l_x3 = x_dataset.getXValue(1, l_subtrahendItem);
0589:                        l_y3 = x_dataset.getYValue(1, l_subtrahendItem);
0590:                        l_subtrahendCurX = new Double(l_x3);
0591:                        l_subtrahendCurY = new Double(l_y3);
0592:
0593:                        if (!b_subtrahendAtIntersect) {
0594:                            l_subtrahendXs.add(l_subtrahendCurX);
0595:                            l_subtrahendYs.add(l_subtrahendCurY);
0596:                        }
0597:
0598:                        l_subtrahendMaxY = Math.max(l_subtrahendMaxY, l_y3);
0599:                        l_subtrahendMinY = Math.min(l_subtrahendMinY, l_y3);
0600:
0601:                        l_x4 = x_dataset.getXValue(1, l_subtrahendItem + 1);
0602:                        l_y4 = x_dataset.getYValue(1, l_subtrahendItem + 1);
0603:                        l_subtrahendNextX = new Double(l_x4);
0604:                        l_subtrahendNextY = new Double(l_y4);
0605:                    }
0606:
0607:                    // deassert b_*FastForward (only matters for 1st time through loop)
0608:                    b_minuendFastForward = false;
0609:                    b_subtrahendFastForward = false;
0610:
0611:                    Double l_intersectX = null;
0612:                    Double l_intersectY = null;
0613:                    boolean b_intersect = false;
0614:
0615:                    b_minuendAtIntersect = false;
0616:                    b_subtrahendAtIntersect = false;
0617:
0618:                    // check for intersect
0619:                    if ((l_x2 == l_x4) && (l_y2 == l_y4)) {
0620:                        // check if line segments are colinear
0621:                        if ((l_x1 == l_x3) && (l_y1 == l_y3)) {
0622:                            b_colinear = true;
0623:                        } else {
0624:                            // the intersect is at the next point for both the minuend 
0625:                            // and subtrahend
0626:                            l_intersectX = new Double(l_x2);
0627:                            l_intersectY = new Double(l_y2);
0628:
0629:                            b_intersect = true;
0630:                            b_minuendAtIntersect = true;
0631:                            b_subtrahendAtIntersect = true;
0632:                        }
0633:                    } else {
0634:                        // compute common denominator
0635:                        double l_denominator = ((l_y4 - l_y3) * (l_x2 - l_x1))
0636:                                - ((l_x4 - l_x3) * (l_y2 - l_y1));
0637:
0638:                        // compute common deltas
0639:                        double l_deltaY = l_y1 - l_y3;
0640:                        double l_deltaX = l_x1 - l_x3;
0641:
0642:                        // compute numerators
0643:                        double l_numeratorA = ((l_x4 - l_x3) * l_deltaY)
0644:                                - ((l_y4 - l_y3) * l_deltaX);
0645:                        double l_numeratorB = ((l_x2 - l_x1) * l_deltaY)
0646:                                - ((l_y2 - l_y1) * l_deltaX);
0647:
0648:                        // check if line segments are colinear
0649:                        if ((0 == l_numeratorA) && (0 == l_numeratorB)
0650:                                && (0 == l_denominator)) {
0651:                            b_colinear = true;
0652:                        } else {
0653:                            // check if previously colinear
0654:                            if (b_colinear) {
0655:                                // clear colinear points and flag
0656:                                l_minuendXs.clear();
0657:                                l_minuendYs.clear();
0658:                                l_subtrahendXs.clear();
0659:                                l_subtrahendYs.clear();
0660:                                l_polygonXs.clear();
0661:                                l_polygonYs.clear();
0662:
0663:                                b_colinear = false;
0664:
0665:                                // set new starting point for the polygon
0666:                                boolean b_useMinuend = ((l_x3 <= l_x1) && (l_x1 <= l_x4));
0667:                                l_polygonXs.add(b_useMinuend ? l_minuendCurX
0668:                                        : l_subtrahendCurX);
0669:                                l_polygonYs.add(b_useMinuend ? l_minuendCurY
0670:                                        : l_subtrahendCurY);
0671:                            }
0672:
0673:                            // compute slope components
0674:                            double l_slopeA = l_numeratorA / l_denominator;
0675:                            double l_slopeB = l_numeratorB / l_denominator;
0676:
0677:                            // check if the line segments intersect
0678:                            if ((0 < l_slopeA) && (l_slopeA <= 1)
0679:                                    && (0 < l_slopeB) && (l_slopeB <= 1)) {
0680:                                // compute the point of intersection
0681:                                double l_xi = l_x1 + (l_slopeA * (l_x2 - l_x1));
0682:                                double l_yi = l_y1 + (l_slopeA * (l_y2 - l_y1));
0683:
0684:                                l_intersectX = new Double(l_xi);
0685:                                l_intersectY = new Double(l_yi);
0686:                                b_intersect = true;
0687:                                b_minuendAtIntersect = ((l_xi == l_x2) && (l_yi == l_y2));
0688:                                b_subtrahendAtIntersect = ((l_xi == l_x4) && (l_yi == l_y4));
0689:
0690:                                // advance minuend and subtrahend to intesect
0691:                                l_minuendCurX = l_intersectX;
0692:                                l_minuendCurY = l_intersectY;
0693:                                l_subtrahendCurX = l_intersectX;
0694:                                l_subtrahendCurY = l_intersectY;
0695:                            }
0696:                        }
0697:                    }
0698:
0699:                    if (b_intersect) {
0700:                        // create the polygon
0701:                        // add the minuend's points to polygon
0702:                        l_polygonXs.addAll(l_minuendXs);
0703:                        l_polygonYs.addAll(l_minuendYs);
0704:
0705:                        // add intersection point to the polygon
0706:                        l_polygonXs.add(l_intersectX);
0707:                        l_polygonYs.add(l_intersectY);
0708:
0709:                        // add the subtrahend's points to the polygon in reverse
0710:                        Collections.reverse(l_subtrahendXs);
0711:                        Collections.reverse(l_subtrahendYs);
0712:                        l_polygonXs.addAll(l_subtrahendXs);
0713:                        l_polygonYs.addAll(l_subtrahendYs);
0714:
0715:                        // create an actual polygon
0716:                        b_positive = (l_subtrahendMaxY <= l_minuendMaxY)
0717:                                && (l_subtrahendMinY <= l_minuendMinY);
0718:                        createPolygon(x_graphics, x_dataArea, x_plot,
0719:                                x_domainAxis, x_rangeAxis, b_positive,
0720:                                l_polygonXs, l_polygonYs);
0721:
0722:                        // clear the point vectors
0723:                        l_minuendXs.clear();
0724:                        l_minuendYs.clear();
0725:                        l_subtrahendXs.clear();
0726:                        l_subtrahendYs.clear();
0727:                        l_polygonXs.clear();
0728:                        l_polygonYs.clear();
0729:
0730:                        // set the maxY and minY values to intersect y-value
0731:                        double l_y = l_intersectY.doubleValue();
0732:                        l_minuendMaxY = l_y;
0733:                        l_subtrahendMaxY = l_y;
0734:                        l_minuendMinY = l_y;
0735:                        l_subtrahendMinY = l_y;
0736:
0737:                        // add interection point to new polygon
0738:                        l_polygonXs.add(l_intersectX);
0739:                        l_polygonYs.add(l_intersectY);
0740:                    }
0741:
0742:                    // advance the minuend if needed
0743:                    if (l_x2 <= l_x4) {
0744:                        l_minuendItem++;
0745:                        b_minuendAdvanced = true;
0746:                    } else {
0747:                        b_minuendAdvanced = false;
0748:                    }
0749:
0750:                    // advance the subtrahend if needed
0751:                    if (l_x4 <= l_x2) {
0752:                        l_subtrahendItem++;
0753:                        b_subtrahendAdvanced = true;
0754:                    } else {
0755:                        b_subtrahendAdvanced = false;
0756:                    }
0757:
0758:                    b_minuendDone = (l_minuendItem == (l_minuendItemCount - 1));
0759:                    b_subtrahendDone = (l_subtrahendItem == (l_subtrahendItemCount - 1));
0760:                }
0761:
0762:                // check if the final polygon needs to be clipped
0763:                if (b_minuendDone && (l_x3 < l_x2) && (l_x2 < l_x4)) {
0764:                    // project onto subtrahend
0765:                    double l_slope = (l_y4 - l_y3) / (l_x4 - l_x3);
0766:                    l_subtrahendNextX = l_minuendNextX;
0767:                    l_subtrahendNextY = new Double((l_slope * l_x2)
0768:                            + (l_y3 - (l_slope * l_x3)));
0769:                }
0770:
0771:                if (b_subtrahendDone && (l_x1 < l_x4) && (l_x4 < l_x2)) {
0772:                    // project onto minuend
0773:                    double l_slope = (l_y2 - l_y1) / (l_x2 - l_x1);
0774:                    l_minuendNextX = l_subtrahendNextX;
0775:                    l_minuendNextY = new Double((l_slope * l_x4)
0776:                            + (l_y1 - (l_slope * l_x1)));
0777:                }
0778:
0779:                // consider last point of minuend and subtrahend for determining positivity
0780:                l_minuendMaxY = Math.max(l_minuendMaxY, l_minuendNextY
0781:                        .doubleValue());
0782:                l_subtrahendMaxY = Math.max(l_subtrahendMaxY, l_subtrahendNextY
0783:                        .doubleValue());
0784:                l_minuendMinY = Math.min(l_minuendMinY, l_minuendNextY
0785:                        .doubleValue());
0786:                l_subtrahendMinY = Math.min(l_subtrahendMinY, l_subtrahendNextY
0787:                        .doubleValue());
0788:
0789:                // add the last point of the minuned and subtrahend
0790:                l_minuendXs.add(l_minuendNextX);
0791:                l_minuendYs.add(l_minuendNextY);
0792:                l_subtrahendXs.add(l_subtrahendNextX);
0793:                l_subtrahendYs.add(l_subtrahendNextY);
0794:
0795:                // create the polygon
0796:                // add the minuend's points to polygon
0797:                l_polygonXs.addAll(l_minuendXs);
0798:                l_polygonYs.addAll(l_minuendYs);
0799:
0800:                // add the subtrahend's points to the polygon in reverse
0801:                Collections.reverse(l_subtrahendXs);
0802:                Collections.reverse(l_subtrahendYs);
0803:                l_polygonXs.addAll(l_subtrahendXs);
0804:                l_polygonYs.addAll(l_subtrahendYs);
0805:
0806:                // create an actual polygon
0807:                b_positive = (l_subtrahendMaxY <= l_minuendMaxY)
0808:                        && (l_subtrahendMinY <= l_minuendMinY);
0809:                createPolygon(x_graphics, x_dataArea, x_plot, x_domainAxis,
0810:                        x_rangeAxis, b_positive, l_polygonXs, l_polygonYs);
0811:            }
0812:
0813:            /**
0814:             * Draws the visual representation of a single data item, second pass.  In 
0815:             * the second pass, the renderer draws the lines and shapes for the 
0816:             * individual points in the two series.
0817:             *
0818:             * @param x_graphics  the graphics device.
0819:             * @param x_dataArea  the area within which the data is being drawn.
0820:             * @param x_info  collects information about the drawing.
0821:             * @param x_plot  the plot (can be used to obtain standard color 
0822:             *         information etc).
0823:             * @param x_domainAxis  the domain (horizontal) axis.
0824:             * @param x_rangeAxis  the range (vertical) axis.
0825:             * @param x_dataset  the dataset.
0826:             * @param x_series  the series index (zero-based).
0827:             * @param x_item  the item index (zero-based).
0828:             * @param x_crosshairState  crosshair information for the plot 
0829:             *                          (<code>null</code> permitted).
0830:             */
0831:            protected void drawItemPass1(Graphics2D x_graphics,
0832:                    Rectangle2D x_dataArea, PlotRenderingInfo x_info,
0833:                    XYPlot x_plot, ValueAxis x_domainAxis,
0834:                    ValueAxis x_rangeAxis, XYDataset x_dataset, int x_series,
0835:                    int x_item, CrosshairState x_crosshairState) {
0836:
0837:                Shape l_entityArea = null;
0838:                EntityCollection l_entities = null;
0839:                if (null != x_info) {
0840:                    l_entities = x_info.getOwner().getEntityCollection();
0841:                }
0842:
0843:                Paint l_seriesPaint = getItemPaint(x_series, x_item);
0844:                Stroke l_seriesStroke = getItemStroke(x_series, x_item);
0845:                x_graphics.setPaint(l_seriesPaint);
0846:                x_graphics.setStroke(l_seriesStroke);
0847:
0848:                PlotOrientation l_orientation = x_plot.getOrientation();
0849:                RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge();
0850:                RectangleEdge l_rangeAxisLocation = x_plot.getRangeAxisEdge();
0851:
0852:                double l_x0 = x_dataset.getXValue(x_series, x_item);
0853:                double l_y0 = x_dataset.getYValue(x_series, x_item);
0854:                double l_x1 = x_domainAxis.valueToJava2D(l_x0, x_dataArea,
0855:                        l_domainAxisLocation);
0856:                double l_y1 = x_rangeAxis.valueToJava2D(l_y0, x_dataArea,
0857:                        l_rangeAxisLocation);
0858:
0859:                if (getShapesVisible()) {
0860:                    Shape l_shape = getItemShape(x_series, x_item);
0861:                    if (l_orientation == PlotOrientation.HORIZONTAL) {
0862:                        l_shape = ShapeUtilities.createTranslatedShape(l_shape,
0863:                                l_y1, l_x1);
0864:                    } else {
0865:                        l_shape = ShapeUtilities.createTranslatedShape(l_shape,
0866:                                l_x1, l_y1);
0867:                    }
0868:                    if (l_shape.intersects(x_dataArea)) {
0869:                        x_graphics.setPaint(getItemPaint(x_series, x_item));
0870:                        x_graphics.fill(l_shape);
0871:                    }
0872:                    l_entityArea = l_shape;
0873:                }
0874:
0875:                // add an entity for the item...
0876:                if (null != l_entities) {
0877:                    if (null == l_entityArea) {
0878:                        l_entityArea = new Rectangle2D.Double((l_x1 - 2),
0879:                                (l_y1 - 2), 4, 4);
0880:                    }
0881:                    String l_tip = null;
0882:                    XYToolTipGenerator l_tipGenerator = getToolTipGenerator(
0883:                            x_series, x_item);
0884:                    if (null != l_tipGenerator) {
0885:                        l_tip = l_tipGenerator.generateToolTip(x_dataset,
0886:                                x_series, x_item);
0887:                    }
0888:                    String l_url = null;
0889:                    XYURLGenerator l_urlGenerator = getURLGenerator();
0890:                    if (null != l_urlGenerator) {
0891:                        l_url = l_urlGenerator.generateURL(x_dataset, x_series,
0892:                                x_item);
0893:                    }
0894:                    XYItemEntity l_entity = new XYItemEntity(l_entityArea,
0895:                            x_dataset, x_series, x_item, l_tip, l_url);
0896:                    l_entities.add(l_entity);
0897:                }
0898:
0899:                int l_domainAxisIndex = x_plot.getDomainAxisIndex(x_domainAxis);
0900:                int l_rangeAxisIndex = x_plot.getRangeAxisIndex(x_rangeAxis);
0901:                updateCrosshairValues(x_crosshairState, l_x0, l_y0,
0902:                        l_domainAxisIndex, l_rangeAxisIndex, l_x1, l_y1,
0903:                        l_orientation);
0904:
0905:                if (0 == x_item) {
0906:                    return;
0907:                }
0908:
0909:                double l_x2 = x_domainAxis.valueToJava2D(x_dataset.getXValue(
0910:                        x_series, (x_item - 1)), x_dataArea,
0911:                        l_domainAxisLocation);
0912:                double l_y2 = x_rangeAxis.valueToJava2D(x_dataset.getYValue(
0913:                        x_series, (x_item - 1)), x_dataArea,
0914:                        l_rangeAxisLocation);
0915:
0916:                Line2D l_line = null;
0917:                if (PlotOrientation.HORIZONTAL == l_orientation) {
0918:                    l_line = new Line2D.Double(l_y1, l_x1, l_y2, l_x2);
0919:                } else if (PlotOrientation.VERTICAL == l_orientation) {
0920:                    l_line = new Line2D.Double(l_x1, l_y1, l_x2, l_y2);
0921:                }
0922:
0923:                if ((null != l_line) && l_line.intersects(x_dataArea)) {
0924:                    x_graphics.setPaint(getItemPaint(x_series, x_item));
0925:                    x_graphics.setStroke(getItemStroke(x_series, x_item));
0926:                    x_graphics.draw(l_line);
0927:                }
0928:            }
0929:
0930:            /**
0931:             * Determines if a dataset is degenerate.  A degenerate dataset is a 
0932:             * dataset where either series has less than two (2) points.
0933:             *
0934:             * @param x_dataset  the dataset.
0935:             * @param x_impliedZeroSubtrahend  if false, do not check the subtrahend
0936:             *
0937:             * @return true if the dataset is degenerate.
0938:             */
0939:            private boolean isEitherSeriesDegenerate(XYDataset x_dataset,
0940:                    boolean x_impliedZeroSubtrahend) {
0941:
0942:                if (x_impliedZeroSubtrahend) {
0943:                    return (x_dataset.getItemCount(0) < 2);
0944:                }
0945:
0946:                return ((x_dataset.getItemCount(0) < 2) || (x_dataset
0947:                        .getItemCount(1) < 2));
0948:            }
0949:
0950:            /**
0951:             * Determines if the two (2) series are disjoint.
0952:             * Disjoint series do not overlap in the domain space.
0953:             *
0954:             * @param x_dataset  the dataset.
0955:             *
0956:             * @return true if the dataset is degenerate.
0957:             */
0958:            private boolean areSeriesDisjoint(XYDataset x_dataset) {
0959:
0960:                int l_minuendItemCount = x_dataset.getItemCount(0);
0961:                double l_minuendFirst = x_dataset.getXValue(0, 0);
0962:                double l_minuendLast = x_dataset.getXValue(0,
0963:                        l_minuendItemCount - 1);
0964:
0965:                int l_subtrahendItemCount = x_dataset.getItemCount(1);
0966:                double l_subtrahendFirst = x_dataset.getXValue(1, 0);
0967:                double l_subtrahendLast = x_dataset.getXValue(1,
0968:                        l_subtrahendItemCount - 1);
0969:
0970:                return ((l_minuendLast < l_subtrahendFirst) || (l_subtrahendLast < l_minuendFirst));
0971:            }
0972:
0973:            /**
0974:             * Draws the visual representation of a polygon
0975:             *
0976:             * @param x_graphics  the graphics device.
0977:             * @param x_dataArea  the area within which the data is being drawn.
0978:             * @param x_plot  the plot (can be used to obtain standard color
0979:             *                information etc).
0980:             * @param x_domainAxis  the domain (horizontal) axis.
0981:             * @param x_rangeAxis  the range (vertical) axis.
0982:             * @param x_positive  indicates if the polygon is positive (true) or 
0983:             *                    negative (false).
0984:             * @param x_xValues  a linked list of the x values (expects values to be 
0985:             *                   of type Double).
0986:             * @param x_yValues  a linked list of the y values (expects values to be 
0987:             *                   of type Double).
0988:             */
0989:            private void createPolygon(Graphics2D x_graphics,
0990:                    Rectangle2D x_dataArea, XYPlot x_plot,
0991:                    ValueAxis x_domainAxis, ValueAxis x_rangeAxis,
0992:                    boolean x_positive, LinkedList x_xValues,
0993:                    LinkedList x_yValues) {
0994:
0995:                PlotOrientation l_orientation = x_plot.getOrientation();
0996:                RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge();
0997:                RectangleEdge l_rangeAxisLocation = x_plot.getRangeAxisEdge();
0998:
0999:                Object[] l_xValues = x_xValues.toArray();
1000:                Object[] l_yValues = x_yValues.toArray();
1001:
1002:                GeneralPath l_path = new GeneralPath();
1003:
1004:                if (PlotOrientation.VERTICAL == l_orientation) {
1005:                    double l_x = x_domainAxis.valueToJava2D(
1006:                            ((Double) l_xValues[0]).doubleValue(), x_dataArea,
1007:                            l_domainAxisLocation);
1008:                    if (this .roundXCoordinates) {
1009:                        l_x = Math.rint(l_x);
1010:                    }
1011:
1012:                    double l_y = x_rangeAxis.valueToJava2D(
1013:                            ((Double) l_yValues[0]).doubleValue(), x_dataArea,
1014:                            l_rangeAxisLocation);
1015:
1016:                    l_path.moveTo((float) l_x, (float) l_y);
1017:                    for (int i = 1; i < l_xValues.length; i++) {
1018:                        l_x = x_domainAxis.valueToJava2D(
1019:                                ((Double) l_xValues[i]).doubleValue(),
1020:                                x_dataArea, l_domainAxisLocation);
1021:                        if (this .roundXCoordinates) {
1022:                            l_x = Math.rint(l_x);
1023:                        }
1024:
1025:                        l_y = x_rangeAxis
1026:                                .valueToJava2D(((Double) l_yValues[i])
1027:                                        .doubleValue(), x_dataArea,
1028:                                        l_rangeAxisLocation);
1029:                        l_path.lineTo((float) l_x, (float) l_y);
1030:                    }
1031:                    l_path.closePath();
1032:                } else {
1033:                    double l_x = x_domainAxis.valueToJava2D(
1034:                            ((Double) l_xValues[0]).doubleValue(), x_dataArea,
1035:                            l_domainAxisLocation);
1036:                    if (this .roundXCoordinates) {
1037:                        l_x = Math.rint(l_x);
1038:                    }
1039:
1040:                    double l_y = x_rangeAxis.valueToJava2D(
1041:                            ((Double) l_yValues[0]).doubleValue(), x_dataArea,
1042:                            l_rangeAxisLocation);
1043:
1044:                    l_path.moveTo((float) l_y, (float) l_x);
1045:                    for (int i = 1; i < l_xValues.length; i++) {
1046:                        l_x = x_domainAxis.valueToJava2D(
1047:                                ((Double) l_xValues[i]).doubleValue(),
1048:                                x_dataArea, l_domainAxisLocation);
1049:                        if (this .roundXCoordinates) {
1050:                            l_x = Math.rint(l_x);
1051:                        }
1052:
1053:                        l_y = x_rangeAxis
1054:                                .valueToJava2D(((Double) l_yValues[i])
1055:                                        .doubleValue(), x_dataArea,
1056:                                        l_rangeAxisLocation);
1057:                        l_path.lineTo((float) l_y, (float) l_x);
1058:                    }
1059:                    l_path.closePath();
1060:                }
1061:
1062:                if (l_path.intersects(x_dataArea)) {
1063:                    x_graphics.setPaint(x_positive ? getPositivePaint()
1064:                            : getNegativePaint());
1065:                    x_graphics.fill(l_path);
1066:                }
1067:            }
1068:
1069:            /**
1070:             * Returns a default legend item for the specified series.  Subclasses 
1071:             * should override this method to generate customised items.
1072:             *
1073:             * @param datasetIndex  the dataset index (zero-based).
1074:             * @param series  the series index (zero-based).
1075:             *
1076:             * @return A legend item for the series.
1077:             */
1078:            public LegendItem getLegendItem(int datasetIndex, int series) {
1079:                LegendItem result = null;
1080:                XYPlot p = getPlot();
1081:                if (p != null) {
1082:                    XYDataset dataset = p.getDataset(datasetIndex);
1083:                    if (dataset != null) {
1084:                        if (getItemVisible(series, 0)) {
1085:                            String label = getLegendItemLabelGenerator()
1086:                                    .generateLabel(dataset, series);
1087:                            String description = label;
1088:                            String toolTipText = null;
1089:                            if (getLegendItemToolTipGenerator() != null) {
1090:                                toolTipText = getLegendItemToolTipGenerator()
1091:                                        .generateLabel(dataset, series);
1092:                            }
1093:                            String urlText = null;
1094:                            if (getLegendItemURLGenerator() != null) {
1095:                                urlText = getLegendItemURLGenerator()
1096:                                        .generateLabel(dataset, series);
1097:                            }
1098:                            Paint paint = lookupSeriesPaint(series);
1099:                            Stroke stroke = lookupSeriesStroke(series);
1100:                            // TODO:  the following hard-coded line needs generalising
1101:                            Line2D line = new Line2D.Double(-7.0, 0.0, 7.0, 0.0);
1102:                            result = new LegendItem(label, description,
1103:                                    toolTipText, urlText, line, stroke, paint);
1104:                            result.setDataset(dataset);
1105:                            result.setDatasetIndex(datasetIndex);
1106:                            result.setSeriesKey(dataset.getSeriesKey(series));
1107:                            result.setSeriesIndex(series);
1108:                        }
1109:                    }
1110:
1111:                }
1112:
1113:                return result;
1114:
1115:            }
1116:
1117:            /**
1118:             * Tests this renderer for equality with an arbitrary object.
1119:             * 
1120:             * @param obj  the object (<code>null</code> permitted).
1121:             * 
1122:             * @return A boolean.
1123:             */
1124:            public boolean equals(Object obj) {
1125:                if (obj == this ) {
1126:                    return true;
1127:                }
1128:                if (!(obj instanceof  XYDifferenceRenderer)) {
1129:                    return false;
1130:                }
1131:                if (!super .equals(obj)) {
1132:                    return false;
1133:                }
1134:                XYDifferenceRenderer that = (XYDifferenceRenderer) obj;
1135:                if (!PaintUtilities.equal(this .positivePaint,
1136:                        that.positivePaint)) {
1137:                    return false;
1138:                }
1139:                if (!PaintUtilities.equal(this .negativePaint,
1140:                        that.negativePaint)) {
1141:                    return false;
1142:                }
1143:                if (this .shapesVisible != that.shapesVisible) {
1144:                    return false;
1145:                }
1146:                if (!ShapeUtilities.equal(this .legendLine, that.legendLine)) {
1147:                    return false;
1148:                }
1149:                if (this .roundXCoordinates != that.roundXCoordinates) {
1150:                    return false;
1151:                }
1152:                return true;
1153:            }
1154:
1155:            /**
1156:             * Returns a clone of the renderer.
1157:             * 
1158:             * @return A clone.
1159:             * 
1160:             * @throws CloneNotSupportedException  if the renderer cannot be cloned.
1161:             */
1162:            public Object clone() throws CloneNotSupportedException {
1163:                XYDifferenceRenderer clone = (XYDifferenceRenderer) super 
1164:                        .clone();
1165:                clone.legendLine = ShapeUtilities.clone(this .legendLine);
1166:                return clone;
1167:            }
1168:
1169:            /**
1170:             * Provides serialization support.
1171:             *
1172:             * @param stream  the output stream.
1173:             *
1174:             * @throws IOException  if there is an I/O error.
1175:             */
1176:            private void writeObject(ObjectOutputStream stream)
1177:                    throws IOException {
1178:                stream.defaultWriteObject();
1179:                SerialUtilities.writePaint(this .positivePaint, stream);
1180:                SerialUtilities.writePaint(this .negativePaint, stream);
1181:                SerialUtilities.writeShape(this .legendLine, stream);
1182:            }
1183:
1184:            /**
1185:             * Provides serialization support.
1186:             *
1187:             * @param stream  the input stream.
1188:             *
1189:             * @throws IOException  if there is an I/O error.
1190:             * @throws ClassNotFoundException  if there is a classpath problem.
1191:             */
1192:            private void readObject(ObjectInputStream stream)
1193:                    throws IOException, ClassNotFoundException {
1194:                stream.defaultReadObject();
1195:                this.positivePaint = SerialUtilities.readPaint(stream);
1196:                this.negativePaint = SerialUtilities.readPaint(stream);
1197:                this.legendLine = SerialUtilities.readShape(stream);
1198:            }
1199:
1200:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.