/**
* Palette for colors.
*
* @author J Clare
* @class ia.ColorPalette
* @constructor
* @param {String[]} c A list of colors.
*/
ia.ColorPalette = function(c)
{
this._colors = new Array();
this.id = "";
this.matchColorsToValues = new Object();
if (c !== undefined) this.setColorList(c);
else this.setColorList(ia.ColorPalette.CATEGORY_COLORS);
};
/**
* A blue numeric color scheme.
*
* @static
* @final
* @property NUMERIC_COLORS
* @type String[]
* @default ['#ece7f2', '#74a9cf', '#023858']
*/
ia.ColorPalette.NUMERIC_COLORS = ['#9EDAE5', '#74a9cf', '#023858'];
/**
* A set of 20 colors for categoric color schemes.
*
* @static
* @final
* @property CATEGORY_COLORS
* @type String[]
* @default [ '#B4371F', '#FFBB78', '#2CA02C','#98DF8A', '#D62728', '#FF9896', '#9467BD', '#C5B0D5', '#8C564B',
* '#C49C94', '#E377C2', '#F7B6D2', '#7F7F7F', '#C7C7C7', '#BCBD22','#DBDB8D', '#17BECF', '#9EDAE5', '#AEC7E8', '#9EDAE5' ]
*/
ia.ColorPalette.CATEGORY_COLORS = [ '#B4371F', '#FFBB78', '#2CA02C',
'#98DF8A', '#D62728', '#FF9896', '#9467BD', '#C5B0D5', '#8C564B',
'#C49C94', '#E377C2', '#F7B6D2', '#7F7F7F', '#C7C7C7', '#BCBD22',
'#DBDB8D', '#17BECF', '#9EDAE5', '#AEC7E8', '#9EDAE5' ];
/**
* The id of the palette.
*
* @property id
* @type String[]
* @default ""
*/
ia.ColorPalette.prototype.id;
/**
* A hash that matches colors to values.
* The key is the value to match against - the value is the color.
*
* @property matchColorsToValues
* @type Associative Array
*/
ia.ColorPalette.prototype.matchColorsToValues;
/**
* Gets the list of colors.
*
* @method getColorList
* @return {String[]} The color list.
*/
ia.ColorPalette.prototype.getColorList = function()
{
return this._colors;
};
/**
* Sets the list of colors.
*
* @method setColorList
* @param {String[]} value The color list.
*/
ia.ColorPalette.prototype.setColorList = function(value)
{
this._colors = value;
};
/**
* Adds a color to this ia.ColorPalette.
*
* @method addColor
* @param {String} c The name of the color.
*/
ia.ColorPalette.prototype.addColor = function(c)
{
this._colors.push(c);
};
/**
* Gets the color at the given index into the palette.
*
* @method getColorAtIndex
* @param {Number} index the Index of the color
* @return {String} the name of the color
*/
ia.ColorPalette.prototype.getColorAtIndex = function(index)
{
return this._colors[index % this._colors.length];
};
/**
* Sets the color at the given index into the palette.
*
* @method setColorAtIndex
* @param {Number} index The index of the color
* @param {String} c The name of the color.
*/
ia.ColorPalette.prototype.setColorAtIndex = function(index, c)
{
this._colors[index] = c;
};
/**
* Returns the colors that are matched against the given values
* in the <code>matchColorsToValues</code> hash.
*
* If no match is found the next color in the palette is used.
*
* If more colors are requested than are contained in the palette,
* random colours are generated to complete the list.
*
* @method getMatchingColors
* @param {String[]} values The values array.
* @return {String[]} An array of color values.
*/
ia.ColorPalette.prototype.getMatchingColors = function(values)
{
var n = values.length;
var colorArray = new Array(n);
var paletteColors = this.getColors(n);
// Get colors for matching values.
for (var i = 0; i < n; i++)
{
if (this.matchColorsToValues[values[i]] !== undefined)
colorArray[i] = this.matchColorsToValues[values[i]];
else
colorArray[i] = paletteColors[i];
}
return colorArray;
};
/**
* Returns the list of colors. If more colors are requested
* than are contained in the palette, random colours are generated
* to complete the list.
*
* @method getColors
* @param {Number} numberOfColors The number of colors required.
* @return {String[]} An array of color values.
*/
ia.ColorPalette.prototype.getColors = function(numberOfColors)
{
var colorArray = new Array(numberOfColors);
var index = 0;
for (var i = 0; i < numberOfColors; i++)
{
if (i < this._colors.length)
colorArray[i] = this._colors[i];
else
{
if (index < ia.ColorPalette.CATEGORY_COLORS.length)
colorArray[i] = ia.ColorPalette.CATEGORY_COLORS[index];
else
colorArray[i] = ia.Color.getRandomColor();
index++;
}
}
return colorArray;
};
/**
* Returns a list of colors uniformly interpolated
* from the <code>color</code> property list. If only one color is requested it
* will be interpolated from the center of the <code>color</code> property list.
* If two colors are requested the first and last
* colors in the <code>color</code> property list will be returned.
*
* @method getInterpolatedColors
* @param {Number} numberOfColors The number of colors required.
* @return {String[]} An array of color values.
*/
ia.ColorPalette.prototype.getInterpolatedColors = function(numberOfColors)
{
var n = this._colors.length;
if (numberOfColors === 1)
{
return [this._colors[0]];
}
else if (numberOfColors === 2)
{
return new Array(this.getColor(0), this.getColor(1));
}
else
{
var interpolatedColors = new Array(numberOfColors);
var fSize = 1 / (numberOfColors-1);
var ratio = 0
for (var i = 0; i < numberOfColors; i++)
{
if (i === 0)
interpolatedColors[i] = this.getColor(0);
else if (i === (numberOfColors-1))
interpolatedColors[i] = this.getColor(1)
else
interpolatedColors[i] = this.getColor(ratio);
ratio += parseFloat(fSize);
}
return interpolatedColors;
}
};
/**
* Gets the color corresponding to the interpolation fraction.
*
* @method getColor
* @param {Number} f An interpolation fraction as a value between 0 and 1.
* @return {String} The color corresponding to the fraction.
*/
ia.ColorPalette.prototype.getColor = function(f)
{
var n = this._colors.length - 1;
var r = 1/n;
if ((n <= 0) || (f <= 0))
{
return this._colors[0];
}
else if (f >= 1)
{
return this._colors[n];
}
else
{
// Interpolate the color.
var color;
var fSize = 1 / n;
var ratio = 0
for (var i = 0; i < n; i++)
{
var r1 = ratio;
var r2 = r1 + fSize;
if ((f >= r1) && (f <= r2))
{
var c1 = this._colors[i];
var c2 = this._colors[i+1];
var adjustedF = (f - r1) / (r2 - r1);
color = ia.Color.getInterpolatedColor(c1, c2, adjustedF);
break;
}
ratio += parseFloat(fSize);
}
return color;
}
};