All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.gsi.chart.renderer.spi.utils.BezierCurve Maven / Gradle / Ivy

Go to download

This charting library ${project.artifactId}- is an extension in the spirit of Oracle's XYChart and performance/time-proven JDataViewer charting functionalities. Emphasis was put on plotting performance for both large number of data points and real-time displays, as well as scientific accuracies leading to error bar/surface plots, and other scientific plotting features (parameter measurements, fitting, multiple axes, zoom, ...).

There is a newer version: 11.2.7
Show newest version
package de.gsi.chart.renderer.spi.utils;

/**
 * small tool class to calculate Bezier Curve control points
 * see: https://en.wikipedia.org/wiki/B%C3%A9zier_curve
 *
 * @author rstein
 */
public final class BezierCurve {

	private BezierCurve() {
		// private math class
	}

	  public static void calcCurveControlPoints(final double[] xData, final double[] yData,
	    		double[] xControlPoint1, double[] yControlPoint1,
	    		double[] xControlPoint2, double[] yControlPoint2, int length) {
	        final int n = length - 1;
	        if (n == 1) { // Special case: Bezier curve should be a straight line.
	            // 3P1 = 2P0 + P3
	        	xControlPoint1[0] = (2 * xData[0] + xData[1]) / 3;
	        	yControlPoint1[0] = (2 * yData[0] + yData[1]) / 3;

	            // P2 = 2P1 – P0
	        	xControlPoint2[0] = 2 * xControlPoint1[0] - xData[0];
	        	yControlPoint2[0] = 2 * yControlPoint1[0] - yData[0];
	            return;
	        }

	        // Calculate first Bezier control points
	        // Right hand side vector
	        final double[] rhs = new double[n];

	        // Set right hand side X values
	        for (int i = 1; i < n - 1; ++i) {
	            rhs[i] = 4 * xData[i] + 2 * xData[i + 1];
	        }
	        rhs[0]     = xData[0] + 2 * xData[1];
	        rhs[n - 1] = (8 * xData[n - 1] + xData[n]) / 2.0;
	        final double[] x = BezierCurve.getFirstControlPoints(rhs);

	        // Set right hand side Y values
	        for (int i = 1; i < n - 1; ++i) {
	            rhs[i] = 4 * yData[i] + 2 * yData[i + 1];
	        }
	        rhs[0]     = yData[0] + 2 * yData[1];
	        rhs[n - 1] = (8 * yData[n - 1] + yData[n]) / 2.0;
	        // Get first control points Y-values
	        final double[] y = BezierCurve.getFirstControlPoints(rhs);

	        // Fill output arrays.

	        // First control points
	        System.arraycopy(x, 0, xControlPoint1, 0, n);
	        System.arraycopy(y, 0, yControlPoint1, 0, n);

	        for (int i = 0; i < n; ++i) {
	            // Second control point
	            if (i < n - 1) {
	            	xControlPoint2[i] = 2 * xData[i + 1] - x[i + 1];
	            	yControlPoint2[i] = 2 * yData[i + 1] - y[i + 1];
	            } else {
	            	xControlPoint2[i] = (xData[n] + x[n - 1]) / 2;
	            	yControlPoint2[i] = (yData[n] + y[n - 1]) / 2;
	            }
	        }
	    }

	    private static double[] getFirstControlPoints(double[] rhs) {
	        final int      n   = rhs.length;
	        final double[] x   = new double[n]; // Solution vector.
	        final double[] tmp = new double[n]; // Temp workspace.
	        double   b   = 2.0;

	        x[0] = rhs[0] / b;

	        for (int i = 1; i < n; i++) {// Decomposition and forward substitution.
	            tmp[i] = 1 / b;
	            b      = (i < n - 1 ? 4.0 : 3.5) - tmp[i];
	            x[i]   = (rhs[i] - x[i - 1]) / b;
	        }
	        for (int i = 1; i < n; i++) {
	            x[n - i - 1] -= tmp[n - i] * x[n - i]; // Backsubstitution.
	        }
	        return x;
	    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy