Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-通过3个点构建样条曲线_Java_Jfreechart - Fatal编程技术网

Java-通过3个点构建样条曲线

Java-通过3个点构建样条曲线,java,jfreechart,Java,Jfreechart,是否可以每3点绘制一次三次样条曲线?我用 XYSplineRenderer r = new XYSplineRenderer(); 和JFreeChart库。例如,Grapher 10(使用“样条线多段线”函数)使用相同的点集构建没有此类折弯的图表,因为Grapher通过每3个点构建一条样条线。是否有机会使用JFreeChart通过每3个点构建样条曲线?我在xysplinederer文档中找不到任何有用的信息 可能对某些人有用: 所以,我理解这种差异XYSPLINEEnderer构建自然三次样

是否可以每3点绘制一次三次样条曲线?我用

XYSplineRenderer r = new XYSplineRenderer();
JFreeChart库。例如,Grapher 10(使用“样条线多段线”函数)使用相同的点集构建没有此类折弯的图表,因为Grapher通过每3个点构建一条样条线。是否有机会使用JFreeChart通过每3个点构建样条曲线?我在xysplinederer文档中找不到任何有用的信息


可能对某些人有用:

所以,我理解这种差异<代码>XYSPLINEEnderer构建自然三次样条插值。 Grapher 10构建单调三次样条插值。这就是区别,很好的例子

样条线渲染器的新代码如下:

package splinedemo;

import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.Vector;
import java.lang.Math;
import static java.lang.Math.sqrt;

import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.event.RendererChangeEvent;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
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;


public class SplineRenderer extends XYLineAndShapeRenderer {

    private Vector points;
    private int precision;

    public SplineRenderer() {
        this(5);
    }

    public SplineRenderer(int precision) {
        super();
        if (precision <= 0) {
            throw new IllegalArgumentException("Requires precision > 0.");
        }
        this.precision = precision;
    }

    public int getPrecision() {
        return this.precision;
    }

    public void setPrecision(int p) {
        if (p <= 0) {
            throw new IllegalArgumentException("Requires p > 0.");
        }
        this.precision = p;
        fireChangeEvent();
    }

    public XYItemRendererState initialise(Graphics2D g2, Rectangle2D dataArea,
            XYPlot plot, XYDataset data, PlotRenderingInfo info) {

        State state = (State) super.initialise(g2, dataArea, plot, data, info);
        state.setProcessVisibleItemsOnly(false);
        this.points = new Vector();
        setDrawSeriesLineAsPath(true);
        return state;
    }

    protected void drawPrimaryLineAsPath(XYItemRendererState state,
            Graphics2D g2, XYPlot plot, XYDataset dataset, int pass,
            int series, int item, ValueAxis domainAxis, ValueAxis rangeAxis,
            Rectangle2D dataArea) {

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

        double x1 = dataset.getXValue(series, item);
        double y1 = dataset.getYValue(series, item);
        double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
        double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);

        // collect points
        if (!Double.isNaN(transX1) && !Double.isNaN(transY1)) {
            ControlPoint p = new ControlPoint(plot.getOrientation()
                                == PlotOrientation.HORIZONTAL ? (float) transY1
                                : (float) transX1, plot.getOrientation()
                                == PlotOrientation.HORIZONTAL ? (float) transX1
                                        : (float) transY1);
            if (!this.points.contains(p)) {
                this.points.add(p);
            }
        }
        if (item == dataset.getItemCount(series) - 1) {
            State s = (State) state;
            // construct path
            if (this.points.size() > 1) {
                ControlPoint cp0 = (ControlPoint) this.points.get(0);
                s.seriesPath.moveTo(cp0.x, cp0.y);
                if (this.points.size() == 2) {
                    // we need at least 3 points to spline. Draw simple line
                    ControlPoint cp1 = (ControlPoint) this.points.get(1);
                    s.seriesPath.lineTo(cp1.x, cp1.y);
                }
                else {
                    int np = this.points.size();
                    double[] d = new double[np]; // Newton form coefficients
                    double[] x = new double[np]; // x-coordinates of nodes

                    for (int i = 0; i < np; i++) {
                        ControlPoint cpi = (ControlPoint) this.points.get(i);
                        x[i] = cpi.x;
                        d[i] = cpi.y;
                    }

                    double[] delta = new double[np-1];
                    for (int i = 0; i < np-1; i++) {
                        delta[i] = (d[i+1] - d[i]) / (x[i+1] - x[i]);
                    }

                    double[] fix = new double[np];
                    double[] m = new double[np];
                    for (int i = 1; i < np-1; i++) {
                        m[i] = (delta[i-1] + delta[i]) / 2;
                        fix[i] = 0;
                    }
                    m[0] = delta[0];
                    m[np-1] = delta[np-2];

                    for (int i = 0; i < np-1; i++) {
                        if (delta[i] == 0) {
                            fix[i] = 1.0;
                            m[i] = 0.0;
                            m[i+1] = 0.0;
                        }
                    }

                    double[] alpha = new double[np];
                    double[] beta = new double[np];
                    double[] dist = new double[np];
                    double[] tau = new double[np];
                    for (int i = 0; i <= np-2; i++) {
                        if (fix[i] == 0.0f) {
                            alpha[i] = m[i]/delta[i];
                            beta[i] = m[i+1]/delta[i];
                            dist[i] = alpha[i]*alpha[i] + beta[i]*beta[i];
                            tau[i] = 3 / sqrt(dist[i]);
                        }
                    }
                    for (int i = 0; i < np; i++) {
                        if (dist[i] > 9) {
                            m[i] = tau[i]*alpha[i]*delta[i];
                            m[i+1] = tau[i]*beta[i]*delta[i];
                        }
                    }

                    double oldt = x[0], t1, t2;
                    double oldy = d[0], t, y;
                    double h00, h01, h10, h11;
                    s.seriesPath.moveTo(oldt, oldy);
                    for (int i = 0; i < np - 1; i++) {
                        // loop over intervals between nodes
                        for (int j = 1; j <= this.precision; j++) {
                            double h = x[i+1] - x[i];
                            t1 = (h * j) / this.precision;
                            t2 = x[i] + t1;
                            t = j/(double) (this.precision);
                            h00 = 2*t*t*t - 3*t*t + 1;
                            h10 = t*t*t - 2*t*t + t;
                            h01 = -2*t*t*t + 3*t*t;
                            h11 = t*t*t - t*t;
                            y = h00*d[i] + h10*h*m[i] + h01*d[i+1] + h11*h*m[i+1];
                            s.seriesPath.lineTo(t2, y);
                        }
                    }
                }
                // draw path
                drawFirstPassShape(g2, pass, series, item, s.seriesPath);
            }
            // reset points vector
            this.points = new Vector();
        }
    }

    public boolean equals(Object obj) {
        if (obj == this)
            return true;
        if (!(obj instanceof SplineRenderer))
            return false;
        SplineRenderer that = (SplineRenderer) obj;
        if (this.precision != that.precision)
            return false;
        return super.equals(obj);
    }


    class ControlPoint {
        public float x;
        public float y;

        public ControlPoint(float x, float y) {
            this.x = x;
            this.y = y;
        }

        public boolean equals(Object obj) {
            if (obj == this)
                return true;
            if (!(obj instanceof ControlPoint))
                return false;
            ControlPoint that = (ControlPoint) obj;
            if (this.x != that.x)
                return false;
            return true;
        }
    }
}
package-splinedemo;
导入java.awt.Graphics2D;
导入java.awt.geom.Rectangle2D;
导入java.util.Vector;
导入java.lang.Math;
导入静态java.lang.Math.sqrt;
导入org.jfree.chart.axis.ValueAxis;
导入org.jfree.chart.event.renderChangeEvent;
导入org.jfree.chart.plot.PlotOrientation;
导入org.jfree.chart.plot.PlotRenderingInfo;
导入org.jfree.chart.plot.XYPlot;
导入org.jfree.chart.renderer.xy.xyitemrenderState;
导入org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
导入org.jfree.data.xy.XYDataset;
导入org.jfree.ui.RectangleEdge;
公共类SplineRenderer扩展了XYLineAndShapeRenderer{
私有向量点;
私有整数精度;
公共Splinderer(){
这(5);
}
公共Splinderer(整数精度){
超级();
如果(精度1){
控制点cp0=(控制点)this.points.get(0);
s、 序列路径moveTo(cp0.x,cp0.y);
if(this.points.size()==2){
//我们至少需要3个点来绘制样条曲线。画一条简单的线
控制点cp1=(控制点)this.points.get(1);
s、 序列路径lineTo(cp1.x,cp1.y);
}
否则{
int np=this.points.size();
double[]d=新的double[np];//牛顿型系数
double[]x=新的double[np];//节点的x坐标
对于(int i=0;i对于(int j=1;j Grapher 10不绘制三次样条线。如果您想要三次样条线,那么您会得到类似JFreeChart的输出。由于JFreeChart唯一的样条线渲染器使用三次样条线,如果您发现三次样条线不合适,您必须使用不同类型的样条线渲染器创建自己的渲染器。我不知道哪种类型的Grapher使用。@JasonC哦,谢谢!有人告诉我grapher10画的是右三次样条曲线,我决定在这里问一下。