📄 pieplot3d.java
字号:
/* =========================================================== * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * * (C) Copyright 2000-2004, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * * This library is free software; you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Foundation; * either version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * -------------- * PiePlot3D.java * -------------- * (C) Copyright 2000-2004, by Object Refinery and Contributors. * * Original Author: Tomer Peretz; * Contributor(s): Richard Atkinson; * David Gilbert (for Object Refinery Limited); * Xun Kang; * Christian W. Zuckschwerdt; * Arnaud Lelievre; * Dave Crane; * * $Id: PiePlot3D.java,v 1.10 2004/05/28 08:25:32 mungady Exp $ * * Changes * ------- * 21-Jun-2002 : Version 1; * 31-Jul-2002 : Modified to use startAngle and direction, drawing modified so that charts * render with foreground alpha < 1.0 (DG); * 05-Aug-2002 : Small modification to draw method to support URLs for HTML image maps (RA); * 26-Sep-2002 : Fixed errors reported by Checkstyle (DG); * 18-Oct-2002 : Added drawing bug fix sent in by Xun Kang, and made a couple of other related * fixes (DG); * 30-Oct-2002 : Changed the PieDataset interface. Fixed another drawing bug (DG); * 12-Nov-2002 : Fixed null pointer exception for zero or negative values (DG); * 07-Mar-2003 : Modified to pass pieIndex on to PieSectionEntity (DG); * 21-Mar-2003 : Added workaround for bug id 620031 (DG); * 26-Mar-2003 : Implemented Serializable (DG); * 30-Jul-2003 : Modified entity constructor (CZ); * 29-Aug-2003 : Small changes for API updates in PiePlot class (DG); * 02-Sep-2003 : Fixed bug where the 'no data' message is not displayed (DG); * 08-Sep-2003 : Added internationalization via use of properties resourceBundle (RFE 690236) (AL); * 29-Oct-2003 : Added workaround for font alignment in PDF output (DG); * 20-Nov-2003 : Fixed bug 845289 (sides not showing) (DG); * 25-Nov-2003 : Added patch (845095) to fix outline paint issues (DG); * 10-Mar-2004 : Numerous changes to enhance labelling (DG); * 31-Mar-2004 : Adjusted plot area when label generator is null (DG); * 08-Apr-2004 : Added flag to PiePlot class to control the treatment of null values (DG); * : Added pieIndex to PieSectionEntity (DG); * */package org.jfree.chart.plot;import java.awt.AlphaComposite;import java.awt.Color;import java.awt.Composite;import java.awt.Font;import java.awt.FontMetrics;import java.awt.Graphics2D;import java.awt.Insets;import java.awt.Paint;import java.awt.Polygon;import java.awt.Shape;import java.awt.Stroke;import java.awt.geom.Arc2D;import java.awt.geom.Area;import java.awt.geom.Ellipse2D;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.io.Serializable;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.jfree.chart.entity.EntityCollection;import org.jfree.chart.entity.PieSectionEntity;import org.jfree.chart.labels.StandardPieItemLabelGenerator;import org.jfree.data.DatasetUtilities;import org.jfree.data.PieDataset;/** * A plot that displays data in the form of a 3D pie chart, using data from * any class that implements the {@link PieDataset} interface. * <P> * Although this class extends {@link PiePlot}, it does not currently support * exploded sections. * * @author Tomer Peretz */public class PiePlot3D extends PiePlot implements Serializable { /** The factor of the depth of the pie from the plot height */ private double depthFactor = 0.2; /** * Creates a pie chart with a three dimensional effect using the specified dataset. * * @param dataset the dataset (<code>null</code> permitted). */ public PiePlot3D(PieDataset dataset) { super(dataset); setCircular(false, false); } /** * Sets the pie depth as a percentage of the height of the plot area. * * @param factor the depth factor (for example, 0.20 is twenty percent). */ public void setDepthFactor(double factor) { this.depthFactor = factor; } /** * The depth factor for the chart. * * @return The depth factor. */ public double getDepthFactor () { return this.depthFactor; } /** * Draws the plot on a Java 2D graphics device (such as the screen or a printer). This * method is called by the {@link org.jfree.chart.JFreeChart} class, you don't normally need * to call it yourself. * * @param g2 the graphics device. * @param plotArea the area within which the plot should be drawn. * @param parentState the state from the parent plot, if there is one. * @param info collects info about the drawing (<code>null</code> permitted). */ public void draw(Graphics2D g2, Rectangle2D plotArea, PlotState parentState, PlotRenderingInfo info) { // adjust for insets... Insets insets = getInsets(); if (insets != null) { plotArea.setRect( plotArea.getX() + insets.left, plotArea.getY() + insets.top, plotArea.getWidth() - insets.left - insets.right, plotArea.getHeight() - insets.top - insets.bottom ); } Rectangle2D originalPlotArea = (Rectangle2D) plotArea.clone(); if (info != null) { info.setPlotArea(plotArea); info.setDataArea(plotArea); } Shape savedClip = g2.getClip(); g2.clip(plotArea); // adjust the plot area by the interior spacing value double gapPercent = getInteriorGap(); double labelPercent = 0.0; if (getLabelGenerator() != null) { labelPercent = getLabelGap() + getMaximumLabelWidth() + getLabelLinkMargin(); } double gapHorizontal = plotArea.getWidth() * (gapPercent + labelPercent); double gapVertical = plotArea.getHeight() * gapPercent; double linkX = plotArea.getX() + gapHorizontal / 2; double linkY = plotArea.getY() + gapVertical / 2; double linkW = plotArea.getWidth() - gapHorizontal; double linkH = plotArea.getHeight() - gapVertical; // make the link area a square if the pie chart is to be circular... if (isCircular()) { // is circular? double min = Math.min(linkW, linkH) / 2; linkX = (linkX + linkX + linkW) / 2 - min; linkY = (linkY + linkY + linkH) / 2 - min; linkW = 2 * min; linkH = 2 * min; } PiePlotState state = initialise(g2, plotArea, this, null, info); // the explode area defines the max circle/ellipse for the exploded pie sections. // it is defined by shrinking the linkArea by the linkMargin factor. double hh = linkW * getLabelLinkMargin(); double vv = linkH * getLabelLinkMargin(); Rectangle2D explodeArea = new Rectangle2D.Double( linkX + hh / 2.0, linkY + vv / 2.0, linkW - hh, linkH - vv ); state.setExplodedPieArea(explodeArea); // the pie area defines the circle/ellipse for regular pie sections. // it is defined by shrinking the explodeArea by the explodeMargin factor. double maximumExplodePercent = getMaximumExplodePercent(); double percent = maximumExplodePercent / (1.0 + maximumExplodePercent); double h1 = explodeArea.getWidth() * percent; double v1 = explodeArea.getHeight() * percent; Rectangle2D pieArea = new Rectangle2D.Double( explodeArea.getX() + h1 / 2.0, explodeArea.getY() + v1 / 2.0, explodeArea.getWidth() - h1, explodeArea.getHeight() - v1 ); int depth = (int) (pieArea.getHeight() * this.depthFactor); // the link area defines the dog-leg point for the linking lines to the labels Rectangle2D linkArea = new Rectangle2D.Double(linkX, linkY, linkW, linkH - depth); state.setLinkArea(linkArea); state.setPieArea(pieArea); state.setPieCenterX(pieArea.getCenterX()); state.setPieCenterY(pieArea.getCenterY() - depth / 2); state.setPieWRadius(pieArea.getWidth() / 2.0); state.setPieHRadius((pieArea.getHeight() - depth) / 2.0); drawBackground(g2, plotArea); // get the data source - return if null; PieDataset dataset = getDataset(); if (DatasetUtilities.isEmptyOrNull(getDataset())) { drawNoDataMessage(g2, plotArea); g2.setClip(savedClip); drawOutline(g2, plotArea); return; } // if too any elements if (dataset.getKeys().size() > plotArea.getWidth()) { String text = "Too many elements"; Font sfont = new Font("dialog", Font.BOLD, 10); g2.setFont(sfont); FontMetrics fm = g2.getFontMetrics(sfont); int stringWidth = fm.stringWidth(text); g2.drawString( text, (int) (plotArea.getX() + (plotArea.getWidth() - stringWidth) / 2), (int) (plotArea.getY() + (plotArea.getHeight() / 2)) ); return; } // if we are drawing a perfect circle, we need to readjust the top left // coordinates of the drawing area for the arcs to arrive at this // effect. if (isCircular()) { double min = Math.min(plotArea.getWidth(), plotArea.getHeight()) / 2; plotArea = new Rectangle2D.Double( plotArea.getCenterX() - min, plotArea.getCenterY() - min, 2 * min, 2 * min ); } // get a list of keys... List sectionKeys = dataset.getKeys(); if (sectionKeys.size() == 0) { return; } // establish the coordinates of the top left corner of the drawing area double arcX = pieArea.getX(); double arcY = pieArea.getY(); //g2.clip(clipArea); Composite originalComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getForegroundAlpha())); double totalValue = DatasetUtilities.calculatePieDatasetTotal(dataset); double runningTotal = 0; if (depth < 0) { return; // if depth is negative don't draw anything } ArrayList arcList = new ArrayList(); Arc2D.Double arc; Paint paint; Paint outlinePaint; Stroke outlineStroke; Iterator iterator = sectionKeys.iterator(); while (iterator.hasNext()) { Comparable currentKey = (Comparable) iterator.next(); Number dataValue = dataset.getValue(currentKey); if (dataValue == null) { arcList.add(null); continue; } double value = dataValue.doubleValue(); if (value <= 0) { arcList.add(null); continue; } double startAngle = getStartAngle(); double direction = getDirection().getFactor(); double angle1 = startAngle + (direction * (runningTotal * 360)) / totalValue; double angle2 = startAngle + (direction * (runningTotal + value) * 360) / totalValue; if (Math.abs(angle2 - angle1) > getMinimumArcAngleToDraw()) { arcList.add( new Arc2D.Double( arcX, arcY + depth, pieArea.getWidth(), pieArea.getHeight() - depth, angle1, angle2 - angle1, Arc2D.PIE ) ); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -