首页>代码>jfreechart免费报表框架demo教程>/jfreechart-1.0.18/experimental/org/jfree/experimental/chart/renderer/xy/XYSmoothLineAndShapeRenderer.java
/* ===========================================================
 * JFreeChart : a free chart library for the Java(tm) platform
 * ===========================================================
 *
 * (C) Copyright 2000-2013, 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.
 *
 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
 * Other names may be trademarks of their respective owners.]
 *
 * ---------------------------------
 * XYSmoothLineAndShapeRenderer.java
 * ---------------------------------
 * (C) Copyright 2007, by Object Refinery Limited and Contributors.
 *
 * Original Author:  -;
 * Contributor(s):   -;
 *
 * Changes
 * -------
 * 14-Jun-2007 : Version 1;
 *
 */

package org.jfree.experimental.chart.renderer.xy;

import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRendererState;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RectangleEdge;

/**
 * A line and shape renderer that performs line smoothing.  See
 * http://www.jfree.org/phpBB2/viewtopic.php?t=20671
 *
 * WARNING: THIS CLASS IS NOT PART OF THE STANDARD JFREECHART API AND IS
 * SUBJECT TO ALTERATION OR REMOVAL.  DO NOT RELY ON THIS CLASS FOR
 * PRODUCTION USE.  Please experiment with this code and provide feedback.
 */
public class XYSmoothLineAndShapeRenderer extends XYLineAndShapeRenderer {

    /**
     * Draws the item (first pass). This method draws the lines
     * connecting the items.
     *
     * @param g2  the graphics device.
     * @param state  the renderer state.
     * @param dataArea  the area within which the data is being drawn.
     * @param plot  the plot (can be used to obtain standard color
     *              information etc).
     * @param domainAxis  the domain axis.
     * @param rangeAxis  the range axis.
     * @param dataset  the dataset.
     * @param pass  the pass.
     * @param series  the series index (zero-based).
     * @param item  the item index (zero-based).
     */
    protected void drawPrimaryLine(XYItemRendererState state, Graphics2D g2,
            XYPlot plot, XYDataset dataset, int pass, int series, int item,
            ValueAxis domainAxis, ValueAxis rangeAxis, Rectangle2D dataArea) {

        if (item == 0) {
            return;
        }

        // get the data point...
        double x1 = dataset.getXValue(series, item);
        double y1 = dataset.getYValue(series, item);
        if (Double.isNaN(y1) || Double.isNaN(x1)) {
            return;
        }

        double x0 = dataset.getXValue(series, item - 1);
        double y0 = dataset.getYValue(series, item - 1);
        if (Double.isNaN(y0) || Double.isNaN(x0)) {
            return;
        }

        RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
        RectangleEdge yAxisLocation = plot.getRangeAxisEdge();

        double transX0 = domainAxis.valueToJava2D(x0, dataArea, xAxisLocation);
        double transY0 = rangeAxis.valueToJava2D(y0, dataArea, yAxisLocation);

        double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
        double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);

        // only draw if we have good values
        if (Double.isNaN(transX0) || Double.isNaN(transY0)
                || Double.isNaN(transX1) || Double.isNaN(transY1)) {
            return;
        }

        Point2D.Double point0 = new Point2D.Double();
        Point2D.Double point1 = new Point2D.Double();
        Point2D.Double point2 = new Point2D.Double();
        Point2D.Double point3 = new Point2D.Double();

        if (item == 1) {
            point0 = null;
        }
        else {
            point0.x = domainAxis.valueToJava2D(dataset.getXValue(series,
                    item - 2), dataArea, xAxisLocation);
            point0.y = rangeAxis.valueToJava2D(dataset.getYValue(series,
                    item - 2), dataArea, yAxisLocation);
        }

        point1.x = transX0;
        point1.y = transY0;

        point2.x = transX1;
        point2.y = transY1;

        if ((item + 1) == dataset.getItemCount(series)) {
            point3 = null;
        }
        else {
            point3.x = domainAxis.valueToJava2D(dataset.getXValue(series,
                    item + 1), dataArea, xAxisLocation);
            point3.y = rangeAxis.valueToJava2D(dataset.getYValue(series,
                    item + 1), dataArea, yAxisLocation);
        }

        int steps = ((int) ((point2.x - point1.x) / 0.2) < 30)
                ? (int) ((point2.x - point1.x) / 0.2) : 30;

        Point2D.Double[] points = getBezierCurve(point0, point1, point2,
                point3, 1, steps);

        for (int i = 1; i < points.length; i++) {
            transX0 = points[i - 1].x;
            transY0 = points[i - 1].y;
            transX1 = points[i].x;
            transY1 = points[i].y;

            PlotOrientation orientation = plot.getOrientation();
            if (orientation == PlotOrientation.HORIZONTAL) {
                state.workingLine.setLine(transY0, transX0, transY1, transX1);
            }
            else if (orientation == PlotOrientation.VERTICAL) {
                state.workingLine.setLine(transX0, transY0, transX1, transY1);
            }

            if (state.workingLine.intersects(dataArea)) {
                drawFirstPassShape(g2, pass, series, item, state.workingLine);
            }
        }
    }

    /**
     * Draws the item shapes and adds chart entities (second pass). This method
     * draws the shapes which mark the item positions. If <code>entities</code>
     * is not <code>null</code> it will be populated with entity information
     * for points that fall within the data area.
     *
     * @param g2  the graphics device.
     * @param plot  the plot (can be used to obtain standard color
     *              information etc).
     * @param domainAxis  the domain axis.
     * @param dataArea  the area within which the data is being drawn.
     * @param rangeAxis  the range axis.
     * @param dataset  the dataset.
     * @param pass  the pass.
     * @param series  the series index (zero-based).
     * @param item  the item index (zero-based).
     * @param crosshairState  the crosshair state.
     * @param entities the entity collection.
     */
    protected void drawSecondaryPass(Graphics2D g2, XYPlot plot,
            XYDataset dataset, int pass, int series, int item,
            ValueAxis domainAxis, Rectangle2D dataArea,
            ValueAxis rangeAxis, CrosshairState crosshairState,
            EntityCollection entities) {
        // super.drawSecondaryPass(g2, plot, dataset, pass, series, item,
        // domainAxis, dataArea, rangeAxis, crosshairState, entities);
    }

    /**
     * Updates the control points.
     *
     * @param point0
     * @param point1
     * @param point2
     * @param point3
     * @param control1
     * @param control2
     * @param smooth
     */
    public static void getControlPoints(Point2D.Double point0,
            Point2D.Double point1, Point2D.Double point2,
            Point2D.Double point3, Point2D.Double control1,
            Point2D.Double control2, double smooth) {

        // Reference: http://www.antigrain.com/research/bezier_interpolation/

        if (point0 == null) {
            point0 = point1;
        } //new Point2D.Double(0, 0);
        if (point3 == null) {
            point3 = point2;
        } //new Point2D.Double(0, 0);

        Point2D.Double c1 = new Point2D.Double(
               (point0.x + point1.x) / 2.0, (point0.y + point1.y) / 2.0);
        Point2D.Double c2 = new Point2D.Double(
               (point1.x + point2.x) / 2.0, (point1.y + point2.y) / 2.0);
        Point2D.Double c3 = new Point2D.Double(
               (point2.x + point3.x) / 2.0, (point2.y + point3.y) / 2.0);

        double len1 = point1.distance(point0);
        double len2 = point2.distance(point1);
        double len3 = point3.distance(point2);

        double k1 = len1 / (len1 + len2);
        double k2 = len2 / (len2 + len3);

        Point2D.Double m1 = new Point2D.Double(
               c1.x + (c2.x - c1.x) * k1, c1.y + (c2.y - c1.y) * k1);
        Point2D.Double m2 = new Point2D.Double(
               c2.x + (c3.x - c2.x) * k2, c2.y + (c3.y - c2.y) * k2);

        control1.setLocation(new Point2D.Double(
               m1.x + (c2.x - m1.x) * smooth + point1.x - m1.x,
               m1.y + (c2.y - m1.y) * smooth + point1.y - m1.y));
        control2.setLocation(new Point2D.Double(
               m2.x + (c2.x - m2.x) * smooth + point2.x - m2.x,
               m2.y + (c2.y - m2.y) * smooth + point2.y - m2.y));
    }

    /**
     * Returns the points for a bezier curve.
     *
     * @param point0
     * @param point1
     * @param point2
     * @param point3
     * @param smooth
     * @param steps
     *
     * @return The curve points.
     */
    public static Point2D.Double[] getBezierCurve(Point2D.Double point0,
            Point2D.Double point1, Point2D.Double point2,
            Point2D.Double point3, double smooth, int steps) {
        Point2D.Double control1 = new Point2D.Double();
        Point2D.Double control2 = new Point2D.Double();

        getControlPoints(point0, point1, point2, point3, control1, control2,
                smooth);

        Point2D.Double C = new Point2D.Double(
               3 * (control1.x - point1.x), 3 * (control1.y - point1.y));
        Point2D.Double B = new Point2D.Double(3 * (control2.x - control1.x)
                - C.x, 3 * (control2.y - control1.y) - C.y);
        Point2D.Double A = new Point2D.Double(point2.x - point1.x - C.x - B.x,
                point2.y - point1.y - C.y - B.y);

        Point2D.Double[] res = new Point2D.Double[steps + 1];
        double stepSize = 1.0 / steps;
        double step = stepSize;

        res[0] = point1;
        for (int i = 1; i < steps; i++) {
            res[i] = new Point2D.Double(A.x * Math.pow(step, 3) + B.x
                    * Math.pow(step, 2) + C.x * step + point1.x, A.y
                    * Math.pow(step, 3) + B.y * Math.pow(step, 2) + C.y * step
                    + point1.y);
            step += stepSize;
        }
        res[steps] = point2;

        return res;
    }

}
最近下载更多
James_hong  LV1 2021年10月13日
y6622576  LV9 2020年6月21日
809933690  LV2 2020年5月21日
wanglong_wang  LV13 2019年8月1日
Weipeng_  LV14 2018年6月28日
pengge  LV2 2016年7月11日
xx511411311  LV3 2016年6月16日
ri0mei  LV2 2016年4月21日
那年那时  LV2 2015年6月18日
hsjsak  LV2 2015年4月23日
最近浏览更多
hhsoft  LV1 2023年10月22日
qq1357574774  LV2 2023年8月14日
abc562311934  LV4 2022年10月8日
东北人  LV12 2022年9月20日
2387972368  LV2 2022年5月25日
heifenglei  LV7 2022年4月7日
wxh1234567  LV4 2022年1月17日
有你的小镇 2021年12月22日
暂无贡献等级
ccxiao  LV2 2021年12月16日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友