package com.one;

/**
 * Класс для построения кривых Безье произвольного порядка.
 * (C) SilentKnight
 */
public class BezierCurve
{
	/**
	 * Построить кривую Безье по заданным точкам.
	 * Построение ведется с разбиением на count точек (count - 1) отрезков.
	 * Порядок кривой определяется числом управляющих точек.
	 * Число управляющих точек должно быть не меньше 2, иначе функция не действует.
	 * И входные, и выходные массивы имеют формат double[n][2],
	 * где первая размерность определяет точку, вторая - координату x или y.
	 *
	 * @param points массив управляющих точек
	 * @param count на сколько точек разбивать кривую (отрезков будет на 1 меньше)
	 * @return массив точек получившейся кривой
	 */
	public static double[][] plotBezierCurve(double[][] points, int count)
	{
		if(points.length < 2 || count <= 0)
		{
			return new double[0][2];
		}
		
		int i, n;
		
		double[] coefs = new double[points.length];
		coefs[0] = 1.0f;
		
		for(n = 1; n < coefs.length; n++)
		{
			for(i = n; i > 0; i--)
			{
				coefs[i] = coefs[i] + coefs[i - 1];
			}
		}
		
		double delta = 1.0f / (double)count;
		double param;
		double value;
		
		int maxpower = points.length - 1;
		
		double[][] data = new double[count--][2];
		
		data[0][0] = points[0][0];
		data[0][1] = points[0][1];
		data[data.length - 1][0] = points[points.length - 1][0];
		data[data.length - 1][1] = points[points.length - 1][1];
		
		for(i = 1; i < count; i++)
		{
			data[i][0] = 0.0f;
			data[i][1] = 0.0f;
			
			param = delta * i;
			
			for(n = 0; n <= maxpower; n++)
			{
				value = coefs[n] * power(param, n) * power(1.0f - param, maxpower - n);
				
				data[i][0] += points[n][0] * value;
				data[i][1] += points[n][1] * value;
			}
		}
		
		return data;
	}
	
	public static double power(double x, int n)
	{
		double r = 1.0f;
		
		for(int i = 0; i < n; i++)
		{
			r *= x;
		}
		
		return r;
	}
}