@Test public void testDrawWithNullDataset() { JFreeChart chart = ChartFactory.createPieChart3D("Test", null); BufferedImage image = new BufferedImage(200 , 100, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = image.createGraphics(); chart.draw(g2, new Rectangle2D.Double(0, 0, 200, 100), null, null); g2.dispose(); }
@Override public void draw(Graphics2D g2, Rectangle2D plotArea, Point2D anchor, PlotState parentState, PlotRenderingInfo info) { RectangleInsets insets = getInsets(); insets.trim(plotArea); Rectangle2D originalPlotArea = (Rectangle2D) plotArea.clone(); if (info != null) { info.setPlotArea(plotArea); info.setDataArea(plotArea); } drawBackground(g2, plotArea); Shape savedClip = g2.getClip(); g2.clip(plotArea); Graphics2D savedG2 = g2; BufferedImage dataImage = null; if (getShadowGenerator() != null) { dataImage = new BufferedImage((int) plotArea.getWidth(), (int) plotArea.getHeight(), BufferedImage.TYPE_INT_ARGB); g2 = dataImage.createGraphics(); g2.translate(-plotArea.getX(), -plotArea.getY()); g2.setRenderingHints(savedG2.getRenderingHints()); originalPlotArea = (Rectangle2D) plotArea.clone(); } double gapPercent = getInteriorGap(); double labelPercent = 0.0; if (getLabelGenerator() != null) { labelPercent = getLabelGap() + getMaximumLabelWidth(); } double gapHorizontal = plotArea.getWidth() * (gapPercent + labelPercent) * 2.0; double gapVertical = plotArea.getHeight() * gapPercent * 2.0; if (DEBUG_DRAW_INTERIOR) { double hGap = plotArea.getWidth() * getInteriorGap(); double vGap = plotArea.getHeight() * getInteriorGap(); double igx1 = plotArea.getX() + hGap; double igx2 = plotArea.getMaxX() - hGap; double igy1 = plotArea.getY() + vGap; double igy2 = plotArea.getMaxY() - vGap; g2.setPaint(Color.LIGHT_GRAY); g2.draw(new Rectangle2D.Double(igx1, igy1, igx2 - igx1, igy2 - igy1)); } double linkX = plotArea.getX() + gapHorizontal / 2; double linkY = plotArea.getY() + gapVertical / 2; double linkW = plotArea.getWidth() - gapHorizontal; double linkH = plotArea.getHeight() - gapVertical; if (isCircular()) { 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); Rectangle2D linkAreaXX = new Rectangle2D.Double(linkX, linkY, linkW, linkH * (1 - this.depthFactor)); state.setLinkArea(linkAreaXX); if (DEBUG_DRAW_LINK_AREA) { g2.setPaint(Color.BLUE); g2.draw(linkAreaXX); g2.setPaint(Color.YELLOW); g2.draw(new Ellipse2D.Double(linkAreaXX.getX(), linkAreaXX.getY(), linkAreaXX.getWidth(), linkAreaXX.getHeight())); } 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); 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); 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); PieDataset dataset = getDataset(); if (DatasetUtilities.isEmptyOrNull(getDataset())) { drawNoDataMessage(g2, plotArea); g2.setClip(savedClip); drawOutline(g2, plotArea); return; } if (dataset.getKeys().size() > plotArea.getWidth()) { String text = localizationResources.getString("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 (isCircular()) { double min = Math.min(plotArea.getWidth(), plotArea.getHeight()) / 2; plotArea = new Rectangle2D.Double(plotArea.getCenterX() - min, plotArea.getCenterY() - min, 2 * min, 2 * min); } List<Comparable> sectionKeys = dataset.getKeys(); if (sectionKeys.isEmpty()) { return; } double arcX = pieArea.getX(); double arcY = pieArea.getY(); Composite originalComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getForegroundAlpha())); double totalValue = DatasetUtilities.calculatePieDatasetTotal(dataset); double runningTotal = 0; if (depth < 0) { return; } ArrayList<Arc2D.Double> arcList = new ArrayList<Arc2D.Double>(); Arc2D.Double arc; Paint paint; Paint outlinePaint; Stroke outlineStroke; for (Comparable currentKey : sectionKeys) { 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 { arcList.add(null); } runningTotal += value; } Shape oldClip = g2.getClip(); Ellipse2D top = new Ellipse2D.Double(pieArea.getX(), pieArea.getY(), pieArea.getWidth(), pieArea.getHeight() - depth); Ellipse2D bottom = new Ellipse2D.Double(pieArea.getX(), pieArea.getY() + depth, pieArea.getWidth(), pieArea.getHeight() - depth); Rectangle2D lower = new Rectangle2D.Double(top.getX(), top.getCenterY(), pieArea.getWidth(), bottom.getMaxY() - top.getCenterY()); Rectangle2D upper = new Rectangle2D.Double(pieArea.getX(), top.getY(), pieArea.getWidth(), bottom.getCenterY() - top.getY()); Area a = new Area(top); a.add(new Area(lower)); Area b = new Area(bottom); b.add(new Area(upper)); Area pie = new Area(a); pie.intersect(b); Area front = new Area(pie); front.subtract(new Area(top)); Area back = new Area(pie); back.subtract(new Area(bottom)); int[] xs; int[] ys; int categoryCount = arcList.size(); for (int categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) { arc = arcList.get(categoryIndex); if (arc == null) { continue; } Comparable key = getSectionKey(categoryIndex); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); g2.setPaint(paint); g2.fill(arc); g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(arc); g2.setPaint(paint); Point2D p1 = arc.getStartPoint(); xs = new int[] {(int) arc.getCenterX(), (int) arc.getCenterX(), (int) p1.getX(), (int) p1.getX()}; ys = new int[] {(int) arc.getCenterY(), (int) arc.getCenterY() - depth, (int) p1.getY() - depth, (int) p1.getY()}; Polygon polygon = new Polygon(xs, ys, 4); g2.setPaint(java.awt.Color.LIGHT_GRAY); g2.fill(polygon); g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(polygon); g2.setPaint(paint); } g2.setPaint(Color.GRAY); g2.fill(back); g2.fill(front); int cat = 0; for (Arc2D.Double segment : arcList) { if (segment != null) { Comparable key = getSectionKey(cat); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); drawSide(g2, pieArea, segment, front, back, paint, outlinePaint, outlineStroke, false, true); } cat++; } cat = 0; for (Arc2D.Double segment : arcList) { if (segment != null) { Comparable key = getSectionKey(cat); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); drawSide(g2, pieArea, segment, front, back, paint, outlinePaint, outlineStroke, true, false); } cat++; } g2.setClip(oldClip); Arc2D upperArc; for (int sectionIndex = 0; sectionIndex < categoryCount; sectionIndex++) { arc = arcList.get(sectionIndex); if (arc == null) { continue; } upperArc = new Arc2D.Double(arcX, arcY, pieArea.getWidth(), pieArea.getHeight() - depth, arc.getAngleStart(), arc.getAngleExtent(), Arc2D.PIE); Comparable currentKey = sectionKeys.get(sectionIndex); paint = lookupSectionPaint(currentKey, true); outlinePaint = lookupSectionOutlinePaint(currentKey); outlineStroke = lookupSectionOutlineStroke(currentKey); g2.setPaint(paint); g2.fill(upperArc); g2.setStroke(outlineStroke); g2.setPaint(outlinePaint); g2.draw(upperArc); if (info != null) { EntityCollection entities = info.getOwner().getEntityCollection(); if (entities != null) { String tip = null; PieToolTipGenerator tipster = getToolTipGenerator(); if (tipster != null) { tip = tipster.generateToolTip(dataset, currentKey); } String url = null; if (getURLGenerator() != null) { url = getURLGenerator().generateURL(dataset, currentKey, getPieIndex()); } PieSectionEntity entity = new PieSectionEntity( upperArc, dataset, getPieIndex(), sectionIndex, currentKey, tip, url); entities.add(entity); } } } List<Comparable> keys = dataset.getKeys(); Rectangle2D adjustedPlotArea = new Rectangle2D.Double( originalPlotArea.getX(), originalPlotArea.getY(), originalPlotArea.getWidth(), originalPlotArea.getHeight() - depth); if (getSimpleLabels()) { drawSimpleLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state); } else { drawLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state); } if (getShadowGenerator() != null) { BufferedImage shadowImage = getShadowGenerator().createDropShadow(dataImage); g2 = savedG2; g2.drawImage(shadowImage, (int) plotArea.getX() + getShadowGenerator().calculateOffsetX(), (int) plotArea.getY() + getShadowGenerator().calculateOffsetY(), null); g2.drawImage(dataImage, (int) plotArea.getX(), (int) plotArea.getY(), null); } g2.setClip(savedClip); g2.setComposite(originalComposite); drawOutline(g2, originalPlotArea); }
PiePlot3D extends PiePlot implements Serializable { @Override public void draw(Graphics2D g2, Rectangle2D plotArea, Point2D anchor, PlotState parentState, PlotRenderingInfo info) { RectangleInsets insets = getInsets(); insets.trim(plotArea); Rectangle2D originalPlotArea = (Rectangle2D) plotArea.clone(); if (info != null) { info.setPlotArea(plotArea); info.setDataArea(plotArea); } drawBackground(g2, plotArea); Shape savedClip = g2.getClip(); g2.clip(plotArea); Graphics2D savedG2 = g2; BufferedImage dataImage = null; if (getShadowGenerator() != null) { dataImage = new BufferedImage((int) plotArea.getWidth(), (int) plotArea.getHeight(), BufferedImage.TYPE_INT_ARGB); g2 = dataImage.createGraphics(); g2.translate(-plotArea.getX(), -plotArea.getY()); g2.setRenderingHints(savedG2.getRenderingHints()); originalPlotArea = (Rectangle2D) plotArea.clone(); } double gapPercent = getInteriorGap(); double labelPercent = 0.0; if (getLabelGenerator() != null) { labelPercent = getLabelGap() + getMaximumLabelWidth(); } double gapHorizontal = plotArea.getWidth() * (gapPercent + labelPercent) * 2.0; double gapVertical = plotArea.getHeight() * gapPercent * 2.0; if (DEBUG_DRAW_INTERIOR) { double hGap = plotArea.getWidth() * getInteriorGap(); double vGap = plotArea.getHeight() * getInteriorGap(); double igx1 = plotArea.getX() + hGap; double igx2 = plotArea.getMaxX() - hGap; double igy1 = plotArea.getY() + vGap; double igy2 = plotArea.getMaxY() - vGap; g2.setPaint(Color.LIGHT_GRAY); g2.draw(new Rectangle2D.Double(igx1, igy1, igx2 - igx1, igy2 - igy1)); } double linkX = plotArea.getX() + gapHorizontal / 2; double linkY = plotArea.getY() + gapVertical / 2; double linkW = plotArea.getWidth() - gapHorizontal; double linkH = plotArea.getHeight() - gapVertical; if (isCircular()) { 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); Rectangle2D linkAreaXX = new Rectangle2D.Double(linkX, linkY, linkW, linkH * (1 - this.depthFactor)); state.setLinkArea(linkAreaXX); if (DEBUG_DRAW_LINK_AREA) { g2.setPaint(Color.BLUE); g2.draw(linkAreaXX); g2.setPaint(Color.YELLOW); g2.draw(new Ellipse2D.Double(linkAreaXX.getX(), linkAreaXX.getY(), linkAreaXX.getWidth(), linkAreaXX.getHeight())); } 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); 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); 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); PieDataset dataset = getDataset(); if (DatasetUtilities.isEmptyOrNull(getDataset())) { drawNoDataMessage(g2, plotArea); g2.setClip(savedClip); drawOutline(g2, plotArea); return; } if (dataset.getKeys().size() > plotArea.getWidth()) { String text = localizationResources.getString("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 (isCircular()) { double min = Math.min(plotArea.getWidth(), plotArea.getHeight()) / 2; plotArea = new Rectangle2D.Double(plotArea.getCenterX() - min, plotArea.getCenterY() - min, 2 * min, 2 * min); } List<Comparable> sectionKeys = dataset.getKeys(); if (sectionKeys.isEmpty()) { return; } double arcX = pieArea.getX(); double arcY = pieArea.getY(); Composite originalComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getForegroundAlpha())); double totalValue = DatasetUtilities.calculatePieDatasetTotal(dataset); double runningTotal = 0; if (depth < 0) { return; } ArrayList<Arc2D.Double> arcList = new ArrayList<Arc2D.Double>(); Arc2D.Double arc; Paint paint; Paint outlinePaint; Stroke outlineStroke; for (Comparable currentKey : sectionKeys) { 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 { arcList.add(null); } runningTotal += value; } Shape oldClip = g2.getClip(); Ellipse2D top = new Ellipse2D.Double(pieArea.getX(), pieArea.getY(), pieArea.getWidth(), pieArea.getHeight() - depth); Ellipse2D bottom = new Ellipse2D.Double(pieArea.getX(), pieArea.getY() + depth, pieArea.getWidth(), pieArea.getHeight() - depth); Rectangle2D lower = new Rectangle2D.Double(top.getX(), top.getCenterY(), pieArea.getWidth(), bottom.getMaxY() - top.getCenterY()); Rectangle2D upper = new Rectangle2D.Double(pieArea.getX(), top.getY(), pieArea.getWidth(), bottom.getCenterY() - top.getY()); Area a = new Area(top); a.add(new Area(lower)); Area b = new Area(bottom); b.add(new Area(upper)); Area pie = new Area(a); pie.intersect(b); Area front = new Area(pie); front.subtract(new Area(top)); Area back = new Area(pie); back.subtract(new Area(bottom)); int[] xs; int[] ys; int categoryCount = arcList.size(); for (int categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) { arc = arcList.get(categoryIndex); if (arc == null) { continue; } Comparable key = getSectionKey(categoryIndex); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); g2.setPaint(paint); g2.fill(arc); g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(arc); g2.setPaint(paint); Point2D p1 = arc.getStartPoint(); xs = new int[] {(int) arc.getCenterX(), (int) arc.getCenterX(), (int) p1.getX(), (int) p1.getX()}; ys = new int[] {(int) arc.getCenterY(), (int) arc.getCenterY() - depth, (int) p1.getY() - depth, (int) p1.getY()}; Polygon polygon = new Polygon(xs, ys, 4); g2.setPaint(java.awt.Color.LIGHT_GRAY); g2.fill(polygon); g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(polygon); g2.setPaint(paint); } g2.setPaint(Color.GRAY); g2.fill(back); g2.fill(front); int cat = 0; for (Arc2D.Double segment : arcList) { if (segment != null) { Comparable key = getSectionKey(cat); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); drawSide(g2, pieArea, segment, front, back, paint, outlinePaint, outlineStroke, false, true); } cat++; } cat = 0; for (Arc2D.Double segment : arcList) { if (segment != null) { Comparable key = getSectionKey(cat); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); drawSide(g2, pieArea, segment, front, back, paint, outlinePaint, outlineStroke, true, false); } cat++; } g2.setClip(oldClip); Arc2D upperArc; for (int sectionIndex = 0; sectionIndex < categoryCount; sectionIndex++) { arc = arcList.get(sectionIndex); if (arc == null) { continue; } upperArc = new Arc2D.Double(arcX, arcY, pieArea.getWidth(), pieArea.getHeight() - depth, arc.getAngleStart(), arc.getAngleExtent(), Arc2D.PIE); Comparable currentKey = sectionKeys.get(sectionIndex); paint = lookupSectionPaint(currentKey, true); outlinePaint = lookupSectionOutlinePaint(currentKey); outlineStroke = lookupSectionOutlineStroke(currentKey); g2.setPaint(paint); g2.fill(upperArc); g2.setStroke(outlineStroke); g2.setPaint(outlinePaint); g2.draw(upperArc); if (info != null) { EntityCollection entities = info.getOwner().getEntityCollection(); if (entities != null) { String tip = null; PieToolTipGenerator tipster = getToolTipGenerator(); if (tipster != null) { tip = tipster.generateToolTip(dataset, currentKey); } String url = null; if (getURLGenerator() != null) { url = getURLGenerator().generateURL(dataset, currentKey, getPieIndex()); } PieSectionEntity entity = new PieSectionEntity( upperArc, dataset, getPieIndex(), sectionIndex, currentKey, tip, url); entities.add(entity); } } } List<Comparable> keys = dataset.getKeys(); Rectangle2D adjustedPlotArea = new Rectangle2D.Double( originalPlotArea.getX(), originalPlotArea.getY(), originalPlotArea.getWidth(), originalPlotArea.getHeight() - depth); if (getSimpleLabels()) { drawSimpleLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state); } else { drawLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state); } if (getShadowGenerator() != null) { BufferedImage shadowImage = getShadowGenerator().createDropShadow(dataImage); g2 = savedG2; g2.drawImage(shadowImage, (int) plotArea.getX() + getShadowGenerator().calculateOffsetX(), (int) plotArea.getY() + getShadowGenerator().calculateOffsetY(), null); g2.drawImage(dataImage, (int) plotArea.getX(), (int) plotArea.getY(), null); } g2.setClip(savedClip); g2.setComposite(originalComposite); drawOutline(g2, originalPlotArea); } }
PiePlot3D extends PiePlot implements Serializable { @Override public void draw(Graphics2D g2, Rectangle2D plotArea, Point2D anchor, PlotState parentState, PlotRenderingInfo info) { RectangleInsets insets = getInsets(); insets.trim(plotArea); Rectangle2D originalPlotArea = (Rectangle2D) plotArea.clone(); if (info != null) { info.setPlotArea(plotArea); info.setDataArea(plotArea); } drawBackground(g2, plotArea); Shape savedClip = g2.getClip(); g2.clip(plotArea); Graphics2D savedG2 = g2; BufferedImage dataImage = null; if (getShadowGenerator() != null) { dataImage = new BufferedImage((int) plotArea.getWidth(), (int) plotArea.getHeight(), BufferedImage.TYPE_INT_ARGB); g2 = dataImage.createGraphics(); g2.translate(-plotArea.getX(), -plotArea.getY()); g2.setRenderingHints(savedG2.getRenderingHints()); originalPlotArea = (Rectangle2D) plotArea.clone(); } double gapPercent = getInteriorGap(); double labelPercent = 0.0; if (getLabelGenerator() != null) { labelPercent = getLabelGap() + getMaximumLabelWidth(); } double gapHorizontal = plotArea.getWidth() * (gapPercent + labelPercent) * 2.0; double gapVertical = plotArea.getHeight() * gapPercent * 2.0; if (DEBUG_DRAW_INTERIOR) { double hGap = plotArea.getWidth() * getInteriorGap(); double vGap = plotArea.getHeight() * getInteriorGap(); double igx1 = plotArea.getX() + hGap; double igx2 = plotArea.getMaxX() - hGap; double igy1 = plotArea.getY() + vGap; double igy2 = plotArea.getMaxY() - vGap; g2.setPaint(Color.LIGHT_GRAY); g2.draw(new Rectangle2D.Double(igx1, igy1, igx2 - igx1, igy2 - igy1)); } double linkX = plotArea.getX() + gapHorizontal / 2; double linkY = plotArea.getY() + gapVertical / 2; double linkW = plotArea.getWidth() - gapHorizontal; double linkH = plotArea.getHeight() - gapVertical; if (isCircular()) { 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); Rectangle2D linkAreaXX = new Rectangle2D.Double(linkX, linkY, linkW, linkH * (1 - this.depthFactor)); state.setLinkArea(linkAreaXX); if (DEBUG_DRAW_LINK_AREA) { g2.setPaint(Color.BLUE); g2.draw(linkAreaXX); g2.setPaint(Color.YELLOW); g2.draw(new Ellipse2D.Double(linkAreaXX.getX(), linkAreaXX.getY(), linkAreaXX.getWidth(), linkAreaXX.getHeight())); } 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); 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); 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); PieDataset dataset = getDataset(); if (DatasetUtilities.isEmptyOrNull(getDataset())) { drawNoDataMessage(g2, plotArea); g2.setClip(savedClip); drawOutline(g2, plotArea); return; } if (dataset.getKeys().size() > plotArea.getWidth()) { String text = localizationResources.getString("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 (isCircular()) { double min = Math.min(plotArea.getWidth(), plotArea.getHeight()) / 2; plotArea = new Rectangle2D.Double(plotArea.getCenterX() - min, plotArea.getCenterY() - min, 2 * min, 2 * min); } List<Comparable> sectionKeys = dataset.getKeys(); if (sectionKeys.isEmpty()) { return; } double arcX = pieArea.getX(); double arcY = pieArea.getY(); Composite originalComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getForegroundAlpha())); double totalValue = DatasetUtilities.calculatePieDatasetTotal(dataset); double runningTotal = 0; if (depth < 0) { return; } ArrayList<Arc2D.Double> arcList = new ArrayList<Arc2D.Double>(); Arc2D.Double arc; Paint paint; Paint outlinePaint; Stroke outlineStroke; for (Comparable currentKey : sectionKeys) { 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 { arcList.add(null); } runningTotal += value; } Shape oldClip = g2.getClip(); Ellipse2D top = new Ellipse2D.Double(pieArea.getX(), pieArea.getY(), pieArea.getWidth(), pieArea.getHeight() - depth); Ellipse2D bottom = new Ellipse2D.Double(pieArea.getX(), pieArea.getY() + depth, pieArea.getWidth(), pieArea.getHeight() - depth); Rectangle2D lower = new Rectangle2D.Double(top.getX(), top.getCenterY(), pieArea.getWidth(), bottom.getMaxY() - top.getCenterY()); Rectangle2D upper = new Rectangle2D.Double(pieArea.getX(), top.getY(), pieArea.getWidth(), bottom.getCenterY() - top.getY()); Area a = new Area(top); a.add(new Area(lower)); Area b = new Area(bottom); b.add(new Area(upper)); Area pie = new Area(a); pie.intersect(b); Area front = new Area(pie); front.subtract(new Area(top)); Area back = new Area(pie); back.subtract(new Area(bottom)); int[] xs; int[] ys; int categoryCount = arcList.size(); for (int categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) { arc = arcList.get(categoryIndex); if (arc == null) { continue; } Comparable key = getSectionKey(categoryIndex); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); g2.setPaint(paint); g2.fill(arc); g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(arc); g2.setPaint(paint); Point2D p1 = arc.getStartPoint(); xs = new int[] {(int) arc.getCenterX(), (int) arc.getCenterX(), (int) p1.getX(), (int) p1.getX()}; ys = new int[] {(int) arc.getCenterY(), (int) arc.getCenterY() - depth, (int) p1.getY() - depth, (int) p1.getY()}; Polygon polygon = new Polygon(xs, ys, 4); g2.setPaint(java.awt.Color.LIGHT_GRAY); g2.fill(polygon); g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(polygon); g2.setPaint(paint); } g2.setPaint(Color.GRAY); g2.fill(back); g2.fill(front); int cat = 0; for (Arc2D.Double segment : arcList) { if (segment != null) { Comparable key = getSectionKey(cat); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); drawSide(g2, pieArea, segment, front, back, paint, outlinePaint, outlineStroke, false, true); } cat++; } cat = 0; for (Arc2D.Double segment : arcList) { if (segment != null) { Comparable key = getSectionKey(cat); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); drawSide(g2, pieArea, segment, front, back, paint, outlinePaint, outlineStroke, true, false); } cat++; } g2.setClip(oldClip); Arc2D upperArc; for (int sectionIndex = 0; sectionIndex < categoryCount; sectionIndex++) { arc = arcList.get(sectionIndex); if (arc == null) { continue; } upperArc = new Arc2D.Double(arcX, arcY, pieArea.getWidth(), pieArea.getHeight() - depth, arc.getAngleStart(), arc.getAngleExtent(), Arc2D.PIE); Comparable currentKey = sectionKeys.get(sectionIndex); paint = lookupSectionPaint(currentKey, true); outlinePaint = lookupSectionOutlinePaint(currentKey); outlineStroke = lookupSectionOutlineStroke(currentKey); g2.setPaint(paint); g2.fill(upperArc); g2.setStroke(outlineStroke); g2.setPaint(outlinePaint); g2.draw(upperArc); if (info != null) { EntityCollection entities = info.getOwner().getEntityCollection(); if (entities != null) { String tip = null; PieToolTipGenerator tipster = getToolTipGenerator(); if (tipster != null) { tip = tipster.generateToolTip(dataset, currentKey); } String url = null; if (getURLGenerator() != null) { url = getURLGenerator().generateURL(dataset, currentKey, getPieIndex()); } PieSectionEntity entity = new PieSectionEntity( upperArc, dataset, getPieIndex(), sectionIndex, currentKey, tip, url); entities.add(entity); } } } List<Comparable> keys = dataset.getKeys(); Rectangle2D adjustedPlotArea = new Rectangle2D.Double( originalPlotArea.getX(), originalPlotArea.getY(), originalPlotArea.getWidth(), originalPlotArea.getHeight() - depth); if (getSimpleLabels()) { drawSimpleLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state); } else { drawLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state); } if (getShadowGenerator() != null) { BufferedImage shadowImage = getShadowGenerator().createDropShadow(dataImage); g2 = savedG2; g2.drawImage(shadowImage, (int) plotArea.getX() + getShadowGenerator().calculateOffsetX(), (int) plotArea.getY() + getShadowGenerator().calculateOffsetY(), null); g2.drawImage(dataImage, (int) plotArea.getX(), (int) plotArea.getY(), null); } g2.setClip(savedClip); g2.setComposite(originalComposite); drawOutline(g2, originalPlotArea); } PiePlot3D();  PiePlot3D(PieDataset dataset); }
PiePlot3D extends PiePlot implements Serializable { @Override public void draw(Graphics2D g2, Rectangle2D plotArea, Point2D anchor, PlotState parentState, PlotRenderingInfo info) { RectangleInsets insets = getInsets(); insets.trim(plotArea); Rectangle2D originalPlotArea = (Rectangle2D) plotArea.clone(); if (info != null) { info.setPlotArea(plotArea); info.setDataArea(plotArea); } drawBackground(g2, plotArea); Shape savedClip = g2.getClip(); g2.clip(plotArea); Graphics2D savedG2 = g2; BufferedImage dataImage = null; if (getShadowGenerator() != null) { dataImage = new BufferedImage((int) plotArea.getWidth(), (int) plotArea.getHeight(), BufferedImage.TYPE_INT_ARGB); g2 = dataImage.createGraphics(); g2.translate(-plotArea.getX(), -plotArea.getY()); g2.setRenderingHints(savedG2.getRenderingHints()); originalPlotArea = (Rectangle2D) plotArea.clone(); } double gapPercent = getInteriorGap(); double labelPercent = 0.0; if (getLabelGenerator() != null) { labelPercent = getLabelGap() + getMaximumLabelWidth(); } double gapHorizontal = plotArea.getWidth() * (gapPercent + labelPercent) * 2.0; double gapVertical = plotArea.getHeight() * gapPercent * 2.0; if (DEBUG_DRAW_INTERIOR) { double hGap = plotArea.getWidth() * getInteriorGap(); double vGap = plotArea.getHeight() * getInteriorGap(); double igx1 = plotArea.getX() + hGap; double igx2 = plotArea.getMaxX() - hGap; double igy1 = plotArea.getY() + vGap; double igy2 = plotArea.getMaxY() - vGap; g2.setPaint(Color.LIGHT_GRAY); g2.draw(new Rectangle2D.Double(igx1, igy1, igx2 - igx1, igy2 - igy1)); } double linkX = plotArea.getX() + gapHorizontal / 2; double linkY = plotArea.getY() + gapVertical / 2; double linkW = plotArea.getWidth() - gapHorizontal; double linkH = plotArea.getHeight() - gapVertical; if (isCircular()) { 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); Rectangle2D linkAreaXX = new Rectangle2D.Double(linkX, linkY, linkW, linkH * (1 - this.depthFactor)); state.setLinkArea(linkAreaXX); if (DEBUG_DRAW_LINK_AREA) { g2.setPaint(Color.BLUE); g2.draw(linkAreaXX); g2.setPaint(Color.YELLOW); g2.draw(new Ellipse2D.Double(linkAreaXX.getX(), linkAreaXX.getY(), linkAreaXX.getWidth(), linkAreaXX.getHeight())); } 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); 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); 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); PieDataset dataset = getDataset(); if (DatasetUtilities.isEmptyOrNull(getDataset())) { drawNoDataMessage(g2, plotArea); g2.setClip(savedClip); drawOutline(g2, plotArea); return; } if (dataset.getKeys().size() > plotArea.getWidth()) { String text = localizationResources.getString("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 (isCircular()) { double min = Math.min(plotArea.getWidth(), plotArea.getHeight()) / 2; plotArea = new Rectangle2D.Double(plotArea.getCenterX() - min, plotArea.getCenterY() - min, 2 * min, 2 * min); } List<Comparable> sectionKeys = dataset.getKeys(); if (sectionKeys.isEmpty()) { return; } double arcX = pieArea.getX(); double arcY = pieArea.getY(); Composite originalComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getForegroundAlpha())); double totalValue = DatasetUtilities.calculatePieDatasetTotal(dataset); double runningTotal = 0; if (depth < 0) { return; } ArrayList<Arc2D.Double> arcList = new ArrayList<Arc2D.Double>(); Arc2D.Double arc; Paint paint; Paint outlinePaint; Stroke outlineStroke; for (Comparable currentKey : sectionKeys) { 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 { arcList.add(null); } runningTotal += value; } Shape oldClip = g2.getClip(); Ellipse2D top = new Ellipse2D.Double(pieArea.getX(), pieArea.getY(), pieArea.getWidth(), pieArea.getHeight() - depth); Ellipse2D bottom = new Ellipse2D.Double(pieArea.getX(), pieArea.getY() + depth, pieArea.getWidth(), pieArea.getHeight() - depth); Rectangle2D lower = new Rectangle2D.Double(top.getX(), top.getCenterY(), pieArea.getWidth(), bottom.getMaxY() - top.getCenterY()); Rectangle2D upper = new Rectangle2D.Double(pieArea.getX(), top.getY(), pieArea.getWidth(), bottom.getCenterY() - top.getY()); Area a = new Area(top); a.add(new Area(lower)); Area b = new Area(bottom); b.add(new Area(upper)); Area pie = new Area(a); pie.intersect(b); Area front = new Area(pie); front.subtract(new Area(top)); Area back = new Area(pie); back.subtract(new Area(bottom)); int[] xs; int[] ys; int categoryCount = arcList.size(); for (int categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) { arc = arcList.get(categoryIndex); if (arc == null) { continue; } Comparable key = getSectionKey(categoryIndex); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); g2.setPaint(paint); g2.fill(arc); g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(arc); g2.setPaint(paint); Point2D p1 = arc.getStartPoint(); xs = new int[] {(int) arc.getCenterX(), (int) arc.getCenterX(), (int) p1.getX(), (int) p1.getX()}; ys = new int[] {(int) arc.getCenterY(), (int) arc.getCenterY() - depth, (int) p1.getY() - depth, (int) p1.getY()}; Polygon polygon = new Polygon(xs, ys, 4); g2.setPaint(java.awt.Color.LIGHT_GRAY); g2.fill(polygon); g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(polygon); g2.setPaint(paint); } g2.setPaint(Color.GRAY); g2.fill(back); g2.fill(front); int cat = 0; for (Arc2D.Double segment : arcList) { if (segment != null) { Comparable key = getSectionKey(cat); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); drawSide(g2, pieArea, segment, front, back, paint, outlinePaint, outlineStroke, false, true); } cat++; } cat = 0; for (Arc2D.Double segment : arcList) { if (segment != null) { Comparable key = getSectionKey(cat); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); drawSide(g2, pieArea, segment, front, back, paint, outlinePaint, outlineStroke, true, false); } cat++; } g2.setClip(oldClip); Arc2D upperArc; for (int sectionIndex = 0; sectionIndex < categoryCount; sectionIndex++) { arc = arcList.get(sectionIndex); if (arc == null) { continue; } upperArc = new Arc2D.Double(arcX, arcY, pieArea.getWidth(), pieArea.getHeight() - depth, arc.getAngleStart(), arc.getAngleExtent(), Arc2D.PIE); Comparable currentKey = sectionKeys.get(sectionIndex); paint = lookupSectionPaint(currentKey, true); outlinePaint = lookupSectionOutlinePaint(currentKey); outlineStroke = lookupSectionOutlineStroke(currentKey); g2.setPaint(paint); g2.fill(upperArc); g2.setStroke(outlineStroke); g2.setPaint(outlinePaint); g2.draw(upperArc); if (info != null) { EntityCollection entities = info.getOwner().getEntityCollection(); if (entities != null) { String tip = null; PieToolTipGenerator tipster = getToolTipGenerator(); if (tipster != null) { tip = tipster.generateToolTip(dataset, currentKey); } String url = null; if (getURLGenerator() != null) { url = getURLGenerator().generateURL(dataset, currentKey, getPieIndex()); } PieSectionEntity entity = new PieSectionEntity( upperArc, dataset, getPieIndex(), sectionIndex, currentKey, tip, url); entities.add(entity); } } } List<Comparable> keys = dataset.getKeys(); Rectangle2D adjustedPlotArea = new Rectangle2D.Double( originalPlotArea.getX(), originalPlotArea.getY(), originalPlotArea.getWidth(), originalPlotArea.getHeight() - depth); if (getSimpleLabels()) { drawSimpleLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state); } else { drawLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state); } if (getShadowGenerator() != null) { BufferedImage shadowImage = getShadowGenerator().createDropShadow(dataImage); g2 = savedG2; g2.drawImage(shadowImage, (int) plotArea.getX() + getShadowGenerator().calculateOffsetX(), (int) plotArea.getY() + getShadowGenerator().calculateOffsetY(), null); g2.drawImage(dataImage, (int) plotArea.getX(), (int) plotArea.getY(), null); } g2.setClip(savedClip); g2.setComposite(originalComposite); drawOutline(g2, originalPlotArea); } PiePlot3D();  PiePlot3D(PieDataset dataset); double getDepthFactor(); void setDepthFactor(double factor); boolean getDarkerSides(); void setDarkerSides(boolean darker); @Override void draw(Graphics2D g2, Rectangle2D plotArea, Point2D anchor,
                     PlotState parentState,
                     PlotRenderingInfo info); @Override String getPlotType(); @Override boolean equals(Object obj); }
PiePlot3D extends PiePlot implements Serializable { @Override public void draw(Graphics2D g2, Rectangle2D plotArea, Point2D anchor, PlotState parentState, PlotRenderingInfo info) { RectangleInsets insets = getInsets(); insets.trim(plotArea); Rectangle2D originalPlotArea = (Rectangle2D) plotArea.clone(); if (info != null) { info.setPlotArea(plotArea); info.setDataArea(plotArea); } drawBackground(g2, plotArea); Shape savedClip = g2.getClip(); g2.clip(plotArea); Graphics2D savedG2 = g2; BufferedImage dataImage = null; if (getShadowGenerator() != null) { dataImage = new BufferedImage((int) plotArea.getWidth(), (int) plotArea.getHeight(), BufferedImage.TYPE_INT_ARGB); g2 = dataImage.createGraphics(); g2.translate(-plotArea.getX(), -plotArea.getY()); g2.setRenderingHints(savedG2.getRenderingHints()); originalPlotArea = (Rectangle2D) plotArea.clone(); } double gapPercent = getInteriorGap(); double labelPercent = 0.0; if (getLabelGenerator() != null) { labelPercent = getLabelGap() + getMaximumLabelWidth(); } double gapHorizontal = plotArea.getWidth() * (gapPercent + labelPercent) * 2.0; double gapVertical = plotArea.getHeight() * gapPercent * 2.0; if (DEBUG_DRAW_INTERIOR) { double hGap = plotArea.getWidth() * getInteriorGap(); double vGap = plotArea.getHeight() * getInteriorGap(); double igx1 = plotArea.getX() + hGap; double igx2 = plotArea.getMaxX() - hGap; double igy1 = plotArea.getY() + vGap; double igy2 = plotArea.getMaxY() - vGap; g2.setPaint(Color.LIGHT_GRAY); g2.draw(new Rectangle2D.Double(igx1, igy1, igx2 - igx1, igy2 - igy1)); } double linkX = plotArea.getX() + gapHorizontal / 2; double linkY = plotArea.getY() + gapVertical / 2; double linkW = plotArea.getWidth() - gapHorizontal; double linkH = plotArea.getHeight() - gapVertical; if (isCircular()) { 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); Rectangle2D linkAreaXX = new Rectangle2D.Double(linkX, linkY, linkW, linkH * (1 - this.depthFactor)); state.setLinkArea(linkAreaXX); if (DEBUG_DRAW_LINK_AREA) { g2.setPaint(Color.BLUE); g2.draw(linkAreaXX); g2.setPaint(Color.YELLOW); g2.draw(new Ellipse2D.Double(linkAreaXX.getX(), linkAreaXX.getY(), linkAreaXX.getWidth(), linkAreaXX.getHeight())); } 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); 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); 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); PieDataset dataset = getDataset(); if (DatasetUtilities.isEmptyOrNull(getDataset())) { drawNoDataMessage(g2, plotArea); g2.setClip(savedClip); drawOutline(g2, plotArea); return; } if (dataset.getKeys().size() > plotArea.getWidth()) { String text = localizationResources.getString("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 (isCircular()) { double min = Math.min(plotArea.getWidth(), plotArea.getHeight()) / 2; plotArea = new Rectangle2D.Double(plotArea.getCenterX() - min, plotArea.getCenterY() - min, 2 * min, 2 * min); } List<Comparable> sectionKeys = dataset.getKeys(); if (sectionKeys.isEmpty()) { return; } double arcX = pieArea.getX(); double arcY = pieArea.getY(); Composite originalComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getForegroundAlpha())); double totalValue = DatasetUtilities.calculatePieDatasetTotal(dataset); double runningTotal = 0; if (depth < 0) { return; } ArrayList<Arc2D.Double> arcList = new ArrayList<Arc2D.Double>(); Arc2D.Double arc; Paint paint; Paint outlinePaint; Stroke outlineStroke; for (Comparable currentKey : sectionKeys) { 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 { arcList.add(null); } runningTotal += value; } Shape oldClip = g2.getClip(); Ellipse2D top = new Ellipse2D.Double(pieArea.getX(), pieArea.getY(), pieArea.getWidth(), pieArea.getHeight() - depth); Ellipse2D bottom = new Ellipse2D.Double(pieArea.getX(), pieArea.getY() + depth, pieArea.getWidth(), pieArea.getHeight() - depth); Rectangle2D lower = new Rectangle2D.Double(top.getX(), top.getCenterY(), pieArea.getWidth(), bottom.getMaxY() - top.getCenterY()); Rectangle2D upper = new Rectangle2D.Double(pieArea.getX(), top.getY(), pieArea.getWidth(), bottom.getCenterY() - top.getY()); Area a = new Area(top); a.add(new Area(lower)); Area b = new Area(bottom); b.add(new Area(upper)); Area pie = new Area(a); pie.intersect(b); Area front = new Area(pie); front.subtract(new Area(top)); Area back = new Area(pie); back.subtract(new Area(bottom)); int[] xs; int[] ys; int categoryCount = arcList.size(); for (int categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) { arc = arcList.get(categoryIndex); if (arc == null) { continue; } Comparable key = getSectionKey(categoryIndex); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); g2.setPaint(paint); g2.fill(arc); g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(arc); g2.setPaint(paint); Point2D p1 = arc.getStartPoint(); xs = new int[] {(int) arc.getCenterX(), (int) arc.getCenterX(), (int) p1.getX(), (int) p1.getX()}; ys = new int[] {(int) arc.getCenterY(), (int) arc.getCenterY() - depth, (int) p1.getY() - depth, (int) p1.getY()}; Polygon polygon = new Polygon(xs, ys, 4); g2.setPaint(java.awt.Color.LIGHT_GRAY); g2.fill(polygon); g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(polygon); g2.setPaint(paint); } g2.setPaint(Color.GRAY); g2.fill(back); g2.fill(front); int cat = 0; for (Arc2D.Double segment : arcList) { if (segment != null) { Comparable key = getSectionKey(cat); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); drawSide(g2, pieArea, segment, front, back, paint, outlinePaint, outlineStroke, false, true); } cat++; } cat = 0; for (Arc2D.Double segment : arcList) { if (segment != null) { Comparable key = getSectionKey(cat); paint = lookupSectionPaint(key); outlinePaint = lookupSectionOutlinePaint(key); outlineStroke = lookupSectionOutlineStroke(key); drawSide(g2, pieArea, segment, front, back, paint, outlinePaint, outlineStroke, true, false); } cat++; } g2.setClip(oldClip); Arc2D upperArc; for (int sectionIndex = 0; sectionIndex < categoryCount; sectionIndex++) { arc = arcList.get(sectionIndex); if (arc == null) { continue; } upperArc = new Arc2D.Double(arcX, arcY, pieArea.getWidth(), pieArea.getHeight() - depth, arc.getAngleStart(), arc.getAngleExtent(), Arc2D.PIE); Comparable currentKey = sectionKeys.get(sectionIndex); paint = lookupSectionPaint(currentKey, true); outlinePaint = lookupSectionOutlinePaint(currentKey); outlineStroke = lookupSectionOutlineStroke(currentKey); g2.setPaint(paint); g2.fill(upperArc); g2.setStroke(outlineStroke); g2.setPaint(outlinePaint); g2.draw(upperArc); if (info != null) { EntityCollection entities = info.getOwner().getEntityCollection(); if (entities != null) { String tip = null; PieToolTipGenerator tipster = getToolTipGenerator(); if (tipster != null) { tip = tipster.generateToolTip(dataset, currentKey); } String url = null; if (getURLGenerator() != null) { url = getURLGenerator().generateURL(dataset, currentKey, getPieIndex()); } PieSectionEntity entity = new PieSectionEntity( upperArc, dataset, getPieIndex(), sectionIndex, currentKey, tip, url); entities.add(entity); } } } List<Comparable> keys = dataset.getKeys(); Rectangle2D adjustedPlotArea = new Rectangle2D.Double( originalPlotArea.getX(), originalPlotArea.getY(), originalPlotArea.getWidth(), originalPlotArea.getHeight() - depth); if (getSimpleLabels()) { drawSimpleLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state); } else { drawLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state); } if (getShadowGenerator() != null) { BufferedImage shadowImage = getShadowGenerator().createDropShadow(dataImage); g2 = savedG2; g2.drawImage(shadowImage, (int) plotArea.getX() + getShadowGenerator().calculateOffsetX(), (int) plotArea.getY() + getShadowGenerator().calculateOffsetY(), null); g2.drawImage(dataImage, (int) plotArea.getX(), (int) plotArea.getY(), null); } g2.setClip(savedClip); g2.setComposite(originalComposite); drawOutline(g2, originalPlotArea); } PiePlot3D();  PiePlot3D(PieDataset dataset); double getDepthFactor(); void setDepthFactor(double factor); boolean getDarkerSides(); void setDarkerSides(boolean darker); @Override void draw(Graphics2D g2, Rectangle2D plotArea, Point2D anchor,
                     PlotState parentState,
                     PlotRenderingInfo info); @Override String getPlotType(); @Override boolean equals(Object obj);  }