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 + -
显示快捷键?