📄 pieplot3d.java
字号:
/* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2007, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* --------------
* PiePlot3D.java
* --------------
* (C) Copyright 2000-2007, 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;
*
* 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);
* 15-Nov-2004 : Removed creation of default tool tip generator (DG);
* 16-Jun-2005 : Added default constructor (DG);
* ------------- JFREECHART 1.0.x ---------------------------------------------
* 27-Sep-2006 : Updated draw() method for new lookup methods (DG);
* 22-Mar-2007 : Added equals() override (DG);
* 18-Jun-2007 : Added handling for simple label option (DG);
* 04-Oct-2007 : Added option to darken sides of plot - thanks to Alex Moots
* (see patch 1805262) (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.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.event.PlotChangeEvent;
import org.jfree.chart.labels.PieToolTipGenerator;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.general.PieDataset;
import org.jfree.ui.RectangleInsets;
/**
* 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.
*/
public class PiePlot3D extends PiePlot implements Serializable {
/** For serialization. */
private static final long serialVersionUID = 3408984188945161432L;
/** The factor of the depth of the pie from the plot height */
private double depthFactor = 0.2;
/**
* A flag that controls whether or not the sides of the pie chart
* are rendered using a darker colour.
*
* @since 1.0.7.
*/
private boolean darkerSides = false; // default preserves previous
// behaviour
/**
* Creates a new instance with no dataset.
*/
public PiePlot3D() {
this(null);
}
/**
* 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);
}
/**
* Returns the depth factor for the chart.
*
* @return The depth factor.
*
* @see #setDepthFactor(double)
*/
public double getDepthFactor() {
return this.depthFactor;
}
/**
* Sets the pie depth as a percentage of the height of the plot area, and
* sends a {@link PlotChangeEvent} to all registered listeners.
*
* @param factor the depth factor (for example, 0.20 is twenty percent).
*
* @see #getDepthFactor()
*/
public void setDepthFactor(double factor) {
this.depthFactor = factor;
notifyListeners(new PlotChangeEvent(this));
}
/**
* Returns a flag that controls whether or not the sides of the pie chart
* are rendered using a darker colour. This is only applied if the
* section colour is an instance of {@link java.awt.Color}.
*
* @return A boolean.
*
* @see #setDarkerSides(boolean)
*
* @since 1.0.7
*/
public boolean getDarkerSides() {
return this.darkerSides;
}
/**
* Sets a flag that controls whether or not the sides of the pie chart
* are rendered using a darker colour, and sends a {@link PlotChangeEvent}
* to all registered listeners. This is only applied if the
* section colour is an instance of {@link java.awt.Color}.
*
* @param darker true to darken the sides, false to use the default
* behaviour.
*
* @see #getDarkerSides()
*
* @since 1.0.7.
*/
public void setDarkerSides(boolean darker) {
this.darkerSides = darker;
notifyListeners(new PlotChangeEvent(this));
}
/**
* 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 anchor the anchor point.
* @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, Point2D anchor,
PlotState parentState,
PlotRenderingInfo info) {
// adjust for insets...
RectangleInsets insets = getInsets();
insets.trim(plotArea);
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.0);
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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -