File: charts/js/CurveUtil.js
/**
* Provides functionality for drawing curves in a series.
*
* @module charts
* @submodule series-curve-util
*/
/**
* Utility class used for calculating curve points.
*
* @class CurveUtil
* @constructor
* @submodule series-curve-util
*/
function CurveUtil()
{
}
CurveUtil.prototype = {
/**
* Creates an array of start, end and control points for splines.
*
* @method getCurveControlPoints
* @param {Array} xcoords Collection of x-coordinates used for calculate the curves
* @param {Array} ycoords Collection of y-coordinates used for calculate the curves
* @return Object
* @protected
*/
getCurveControlPoints: function(xcoords, ycoords)
{
var outpoints = [],
i = 1,
l = xcoords.length - 1,
xvals = [],
yvals = [];
// Too few points, need at least two
if (l < 1)
{
return null;
}
outpoints[0] = {
startx: xcoords[0],
starty: ycoords[0],
endx: xcoords[1],
endy: ycoords[1]
};
// Special case, the Bezier should be a straight line
if (l === 1)
{
outpoints[0].ctrlx1 = (2.0*xcoords[0] + xcoords[1])/3.0;
outpoints[0].ctrly2 = (2.0*ycoords[0] + ycoords[1])/3.0;
outpoints[0].ctrlx2 = 2.0*outpoints[0].ctrlx1 - xcoords[0];
outpoints[0].ctrly2 = 2.0*outpoints[0].ctrly1 - ycoords[0];
return outpoints;
}
for (; i < l; ++i)
{
outpoints.push({
startx: Math.round(xcoords[i]),
starty: Math.round(ycoords[i]),
endx: Math.round(xcoords[i+1]),
endy: Math.round(ycoords[i+1])
});
xvals[i] = 4.0 * xcoords[i] + 2*xcoords[i+1];
yvals[i] = 4.0*ycoords[i] + 2*ycoords[i+1];
}
xvals[0] = xcoords[0] + (2.0 * xcoords[1]);
xvals[l-1] = (8.0 * xcoords[l-1] + xcoords[l]) / 2.0;
xvals = this.getControlPoints(xvals.concat());
yvals[0] = ycoords[0] + (2.0 * ycoords[1]);
yvals[l-1] = (8.0 * ycoords[l-1] + ycoords[l]) / 2.0;
yvals = this.getControlPoints(yvals.concat());
for (i = 0; i < l; ++i)
{
outpoints[i].ctrlx1 = Math.round(xvals[i]);
outpoints[i].ctrly1 = Math.round(yvals[i]);
if (i < l-1)
{
outpoints[i].ctrlx2 = Math.round(2*xcoords[i+1] - xvals[i+1]);
outpoints[i].ctrly2 = Math.round(2*ycoords[i+1] - yvals[i+1]);
}
else
{
outpoints[i].ctrlx2 = Math.round((xcoords[l] + xvals[l-1])/2);
outpoints[i].ctrly2 = Math.round((ycoords[l] + yvals[l-1])/2);
}
}
return outpoints;
},
/**
* Gets the control points for the curve.
*
* @method getControlPoints
* @param {Array} vals Collection of values coords used to generate control points.
* @return Array
* @private
*/
getControlPoints: function(vals)
{
var l = vals.length,
x = [],
tmp = [],
b = 2.0,
i = 1;
x[0] = vals[0] / b;
for (; i < l; ++i)
{
tmp[i] = 1/b;
b = (i < l-1 ? 4.0 : 3.5) - tmp[i];
x[i] = (vals[i] - x[i-1]) / b;
}
for (i = 1; i < l; ++i)
{
x[l-i-1] -= tmp[l-i] * x[l-i];
}
return x;
}
};
Y.CurveUtil = CurveUtil;