spiderwebplot.java
来自「JfreeChart 常用图表例子」· Java 代码 · 共 1,150 行 · 第 1/3 页
JAVA
1,150 行
keys = this.dataset.getColumnKeys(); } if (keys != null) { int series = 0; Iterator iterator = keys.iterator(); Shape shape = getLegendItemShape(); while (iterator.hasNext()) { String label = iterator.next().toString(); String description = label; Paint paint = getSeriesPaint(series); Paint outlinePaint = getSeriesOutlinePaint(series); Stroke stroke = getSeriesOutlineStroke(series); LegendItem item = new LegendItem( label, description, null, null, shape, paint, stroke, outlinePaint ); result.add(item); series++; } } return result; } /** * Returns a cartesian point from a polar angle, length and bounding box * * @param bounds the area inside which the point needs to be. * @param angle the polar angle, in degrees. * @param length the relative length. Given in percent of maximum extend. * * @return The cartesian point. */ protected Point2D getWebPoint(Rectangle2D bounds, double angle, double length) { double angrad = Math.toRadians(angle); double x = Math.cos(angrad) * length * bounds.getWidth() / 2; double y = -Math.sin(angrad) * length * bounds.getHeight() / 2; return new Point2D.Double( bounds.getX() + x + bounds.getWidth() / 2, bounds.getY() + y + bounds.getHeight() / 2 ); } /** * Draws the plot on a Java 2D graphics device (such as the screen or a * printer). * * @param g2 the graphics device. * @param area the area within which the plot should be drawn. * @param anchor the anchor point (<code>null</code> permitted). * @param parentState the state from the parent plot, if there is one. * @param info collects info about the drawing. */ public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor, PlotState parentState, PlotRenderingInfo info) { // adjust for insets... RectangleInsets insets = getInsets(); insets.trim(area); if (info != null) { info.setPlotArea(area); info.setDataArea(area); } drawBackground(g2, area); drawOutline(g2, area); Shape savedClip = g2.getClip(); g2.clip(area); Composite originalComposite = g2.getComposite(); g2.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, getForegroundAlpha() ) ); if (!DatasetUtilities.isEmptyOrNull(this.dataset)) { int seriesCount = 0, catCount = 0; if (this.dataExtractOrder == TableOrder.BY_ROW) { seriesCount = this.dataset.getRowCount(); catCount = this.dataset.getColumnCount(); } else { seriesCount = this.dataset.getColumnCount(); catCount = this.dataset.getRowCount(); } // ensure we have a maximum value to use on the axes if (this.maxValue == DEFAULT_MAX_VALUE) calculateMaxValue(seriesCount, catCount); // Next, setup the plot area // adjust the plot area by the interior spacing value double gapHorizontal = area.getWidth() * getInteriorGap(); double gapVertical = area.getHeight() * getInteriorGap(); double X = area.getX() + gapHorizontal / 2; double Y = area.getY() + gapVertical / 2; double W = area.getWidth() - gapHorizontal; double H = area.getHeight() - gapVertical; double headW = area.getWidth() * this.headPercent; double headH = area.getHeight() * this.headPercent; // make the chart area a square double min = Math.min(W, H) / 2; X = (X + X + W) / 2 - min; Y = (Y + Y + H) / 2 - min; W = 2 * min; H = 2 * min; Point2D centre = new Point2D.Double(X + W / 2, Y + H / 2); Rectangle2D radarArea = new Rectangle2D.Double(X, Y, W, H); // Now actually plot each of the series polygons.. for (int series = 0; series < seriesCount; series++) { drawRadarPoly( g2, radarArea, centre, info, series, catCount, headH, headW ); } } else { drawNoDataMessage(g2, area); } g2.clip(savedClip); g2.setComposite(originalComposite); drawOutline(g2, area); } /** * loop through each of the series to get the maximum value * on each category axis * * @param seriesCount the number of series * @param catCount the number of categories */ private void calculateMaxValue(int seriesCount, int catCount) { double v = 0; Number nV = null; for (int seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) { for (int catIndex = 0; catIndex < catCount; catIndex++) { nV = getPlotValue(seriesIndex, catIndex); if (nV != null) { v = nV.doubleValue(); if (v > this.maxValue) { this.maxValue = v; } } } } } /** * Draws a radar plot polygon. * * @param g2 the graphics device. * @param plotArea the area we are plotting in (already adjusted). * @param centre the centre point of the radar axes * @param info chart rendering info. * @param series the series within the dataset we are plotting * @param catCount the number of categories per radar plot * @param headH the data point height * @param headW the data point width */ protected void drawRadarPoly(Graphics2D g2, Rectangle2D plotArea, Point2D centre, PlotRenderingInfo info, int series, int catCount, double headH, double headW) { Polygon polygon = new Polygon(); // plot the data... for (int cat = 0; cat < catCount; cat++) { Number dataValue = getPlotValue(series, cat); if (dataValue != null) { double value = dataValue.doubleValue(); if (value > 0) { // draw the polygon series... // Finds our starting angle from the centre for this axis double angle = getStartAngle() + (getDirection().getFactor() * cat * 360 / catCount); // The following angle calc will ensure there isn't a top // vertical axis - this may be useful if you don't want any // given criteria to 'appear' move important than the // others.. // + (getDirection().getFactor() // * (cat + 0.5) * 360 / catCount); // find the point at the appropriate distance end point // along the axis/angle identified above and add it to the // polygon Point2D point = getWebPoint( plotArea, angle, value / this.maxValue ); polygon.addPoint((int) point.getX(), (int) point.getY()); // put an elipse at the point being plotted.. // TODO add tooltip/URL capability to this elipse Paint paint = getSeriesPaint(series); Paint outlinePaint = getSeriesOutlinePaint(series); Stroke outlineStroke = getSeriesOutlineStroke(series); Ellipse2D head = new Ellipse2D.Double( point.getX() - headW / 2, point.getY() - headH / 2, headW, headH ); g2.setPaint(paint); g2.fill(head); g2.setStroke(outlineStroke); g2.setPaint(outlinePaint); g2.draw(head); // then draw the axis and category label, but only on the // first time through..... if (series == 0) { Point2D endPoint = getWebPoint(plotArea, angle, 1); // 1 = end of axis Line2D line = new Line2D.Double(centre, endPoint); g2.draw(line); drawLabel( g2, plotArea, value, cat, angle, 360.0 / catCount ); } } } } // Plot the polygon Paint paint = getSeriesPaint(series); g2.setPaint(paint); g2.draw(polygon); // Lastly, fill the web polygon if this is required if (this.webFilled) { g2.setComposite( AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f) ); g2.fill(polygon); g2.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, getForegroundAlpha() ) ); } } /** * Returns the value to be plotted at the interseries of the * series and the category. This allows us to plot * BY_ROW or BY_COLUMN which basically is just reversing the * definition of the categories and data series being plotted * * @param series the series to be plotted * @param cat the category within the series to be plotted * * @return The value to be plotted */ Number getPlotValue(int series, int cat) { Number value = null; if (this.dataExtractOrder == TableOrder.BY_ROW) { value = this.dataset.getValue(series, cat); } else if (this.dataExtractOrder == TableOrder.BY_COLUMN) { value = this.dataset.getValue(cat, series); } return value; } /** * Draws the label for one axis. * * @param g2 the graphics device. * @param plotArea the plot area * @param value the value of the label. * @param cat the category (zero-based index). * @param startAngle the starting angle. * @param extent the extent of the arc. */ protected void drawLabel(Graphics2D g2, Rectangle2D plotArea, double value, int cat, double startAngle, double extent) { FontRenderContext frc = g2.getFontRenderContext(); String label = null; if (this.dataExtractOrder == TableOrder.BY_ROW) { // if series are in rows, then the categories are the column keys label = this.labelGenerator.generateColumnLabel(this.dataset, cat); } else { // if series are in columns, then the categories are the row keys label = this.labelGenerator.generateRowLabel(this.dataset, cat); } Rectangle2D labelBounds = getLabelFont().getStringBounds(label, frc); LineMetrics lm = getLabelFont().getLineMetrics(label, frc); double ascent = lm.getAscent(); Point2D labelLocation = calculateLabelLocation( labelBounds, ascent, plotArea, startAngle ); Composite saveComposite = g2.getComposite(); g2.setComposite( AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f) ); g2.setPaint(getLabelPaint()); g2.setFont(getLabelFont()); g2.drawString( label, (float) labelLocation.getX(), (float) labelLocation.getY() ); g2.setComposite(saveComposite); } /** * Returns the location for a label * * @param labelBounds the label bounds. * @param ascent the ascent (height of font). * @param plotArea the plot area * @param startAngle the start angle for the pie series. * * @return The location for a label. */ protected Point2D calculateLabelLocation(Rectangle2D labelBounds, double ascent, Rectangle2D plotArea, double startAngle) { Arc2D arc1 = new Arc2D.Double(plotArea, startAngle, 0, Arc2D.OPEN); Point2D point1 = arc1.getEndPoint(); double deltaX = -(point1.getX() - plotArea.getCenterX()) * this.axisLabelGap; double deltaY = -(point1.getY() - plotArea.getCenterY()) * this.axisLabelGap; double labelX = point1.getX() - deltaX; double labelY = point1.getY() - deltaY; if (labelX < plotArea.getCenterX()) { labelX -= labelBounds.getWidth(); } if (labelX == plotArea.getCenterX()) { labelX -= labelBounds.getWidth() / 2; } if (labelY > plotArea.getCenterY()) { labelY += ascent; } return new Point2D.Double(labelX, labelY); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?