Based on this decision , to solve question number 2, the following algorithm swaps the colors around the midpoint of the pie. Two parameters:
- pNbColors - the number of slices in the pie
- pNonAdjacentSimilarColor a Boolean to indicate whether you want adjacent similar colors or not.
I use ColorHSL , ColorRGB and ColorUtils (see below).
public static function ColorArrayGenerator( pNbColors:int, pNonAdjacentSimilarColor:Boolean = false):Array { var colors:Array = new Array(); var baseRGB:ColorRGB = new ColorRGB(); baseRGB.setRGBFromUint(0x8A56E2); var baseHSL:ColorHSL = new ColorHSL(); rgbToHsl(baseHSL, baseRGB); var currentHue:Number = baseHSL.Hue; colors.push(baseRGB.getUintFromRGB()); var step:Number = (360.0 / pNbColors); var nextHSL:ColorHSL; var nextRGB:ColorRGB; var i:int; for (i = 1; i < pNbColors; i++) { currentHue += step; if (currentHue > 360) { currentHue -= 360; } nextHSL = new ColorHSL(currentHue, baseHSL.Saturation, aseHSL.Luminance); nextRGB = new ColorRGB(); hslToRgb(nextRGB, nextHSL); colors.push(nextRGB.getUintFromRGB()); } if (pNonAdjacentSimilarColor == true && pNbColors > 2) { var holder:uint = 0; var j:int; for (i = 0, j = pNbColors / 2; i < pNbColors / 2; i += 2, j += 2) { holder = colors[i]; colors[i] = colors[j]; colors[j] = holder; } } return colors; }
This leads to the exit of the right side:

ColorHSL Class:
final public class ColorHSL { private var _hue:Number; // 0.0 .. 359.99999 private var _sat:Number; // 0.0 .. 100.0 private var _lum:Number; // 0.0 .. 100.0 public function ColorHSL( hue:Number = 0, sat:Number = 0, lum:Number = 0) { _hue = hue; _sat = sat; _lum = lum; } [Bindable]public function get Hue():Number { return _hue; } public function set Hue(value:Number):void { if (value > 360) { _hue = value % 360; } // remember, hue is modulo 360 else if (value < 0) { _hue = 0; } else { _hue = value; } } [Bindable]public function get Saturation():Number { return _sat; } public function set Saturation(value:Number):void { if (value > 100.0) { _sat = 100.0; } else if (value < 0) { _sat = 0; } else { _sat = value; } } [Bindable]public function get Luminance():Number { return _lum; } public function set Luminance(value:Number):void { if (value > 100.0) { _lum = 100.0; } else if (value < 0) { _lum = 0; } else { _lum = value; } } }
ColorRGB Class:
final public class ColorRGB { private var _red:uint; private var _grn:uint; private var _blu:uint; private var _rgb:uint;
ColorUtils Class:
final public class ColorUtils { public static function HSV2RGB(hue:Number, sat:Number, val:Number):uint { var red:Number = 0; var grn:Number = 0; var blu:Number = 0; var i:Number; var f:Number; var p:Number; var q:Number; var t:Number; hue%=360; sat/=100; val/=100; hue/=60; i = Math.floor(hue); f = hue-i; p = val*(1-sat); q = val*(1-(sat*f)); t = val*(1-(sat*(1-f))); if (i==0) { red=val; grn=t; blu=p; } else if (i==1) { red=q; grn=val; blu=p; } else if (i==2) { red=p; grn=val; blu=t; } else if (i==3) { red=p; grn=q; blu=val; } else if (i==4) { red=t; grn=p; blu=val; } else if (i==5) { red=val; grn=p; blu=q; } red = Math.floor(red*255); grn = Math.floor(grn*255); blu = Math.floor(blu*255); return (red<<16) | (grn << 8) | (blu); } // public static function RGB2HSV(pColor:uint):Object { var red:uint = (pColor >> 16) & 0xff; var grn:uint = (pColor >> 8) & 0xff; var blu:uint = pColor & 0xff; var x:Number; var val:Number; var f:Number; var i:Number; var hue:Number; var sat:Number; red/=255; grn/=255; blu/=255; x = Math.min(Math.min(red, grn), blu); val = Math.max(Math.max(red, grn), blu); if (x==val){ return({h:undefined, s:0, v:val*100}); } f = (red == x) ? grn-blu : ((grn == x) ? blu-red : red-grn); i = (red == x) ? 3 : ((grn == x) ? 5 : 1); hue = Math.floor((if/(val-x))*60)%360; sat = Math.floor(((val-x)/val)*100); val = Math.floor(val*100); return({h:hue, s:sat, v:val}); } /** * Generates an array of pNbColors colors (uint) * The colors are generated to fill a pie chart (meaning that they circle back to the starting color) * @param pNbColors The number of colors to generate (ex: Number of slices in the pie chart) * @param pNonAdjacentSimilarColor Should the colors stay Adjacent or not ? */ public static function ColorArrayGenerator( pNbColors:int, pNonAdjacentSimilarColor:Boolean = false):Array { // Based on http://www.flexspectrum.com/?p=10 var colors:Array = []; var baseRGB:ColorRGB = new ColorRGB(); baseRGB.setRGBFromUint(0x8A56E2); var baseHSL:ColorHSL = new ColorHSL(); rgbToHsl(baseHSL, baseRGB); var currentHue:Number = baseHSL.Hue; colors.push(baseRGB.getUintFromRGB()); var step:Number = (360.0 / pNbColors); var nextHSL:ColorHSL; var nextRGB:ColorRGB; var i:int; for (i = 1; i < pNbColors; i++) { currentHue += step; if (currentHue > 360) { currentHue -= 360; } nextHSL = new ColorHSL(currentHue, baseHSL.Saturation, baseHSL.Luminance); nextRGB = new ColorRGB(); hslToRgb(nextRGB, nextHSL); colors.push(nextRGB.getUintFromRGB()); } if (pNonAdjacentSimilarColor == true && pNbColors > 2) { var holder:uint = 0; var j:int; for (i = 0, j = pNbColors / 2; i < pNbColors / 2; i += 2, j += 2) { holder = colors[i]; colors[i] = colors[j]; colors[j] = holder; } } return colors; } static public function rgbToHsl(hsl:ColorHSL, rgb:ColorRGB):void { var h:Number = 0; var s:Number = 0; var l:Number = 0; // Normalizes incoming RGB values. // var dRed:Number = (Number)(rgb.red / 255.0); var dGrn:Number = (Number)(rgb.grn / 255.0); var dBlu:Number = (Number)(rgb.blu / 255.0); var dMax:Number = Math.max(dRed, Math.max(dGrn, dBlu)); var dMin:Number = Math.min(dRed, Math.min(dGrn, dBlu)); //------------------------- // hue // if (dMax == dMin) { h = 0; // undefined } else if (dMax == dRed && dGrn >= dBlu) { h = 60.0 * (dGrn - dBlu) / (dMax - dMin); } else if (dMax == dRed && dGrn < dBlu) { h = 60.0 * (dGrn - dBlu) / (dMax - dMin) + 360.0; } else if (dMax == dGrn) { h = 60.0 * (dBlu - dRed) / (dMax-dMin) + 120.0; } else if (dMax == dBlu) { h = 60.0 * (dRed - dGrn) / (dMax - dMin) + 240.0; } //------------------------- // luminance // l = (dMax + dMin) / 2.0; //------------------------- // saturation // if (l == 0 || dMax == dMin) { s = 0; } else if (0 < l && l <= 0.5) { s = (dMax - dMin) / (dMax + dMin); } else if (l>0.5) { s = (dMax - dMin) / (2 - (dMax + dMin)); //(dMax-dMin > 0)? } hsl.Hue = h; hsl.Luminance = l; hsl.Saturation = s; } // rgbToHsl //--------------------------------------- // Convert the input RGB values to the corresponding HSL values. // static public function hslToRgb(rgb:ColorRGB, hsl:ColorHSL):void { if (hsl.Saturation == 0) { // Achromatic color case, luminance only. // var lumScaled:int = (int)(hsl.Luminance * 255.0); rgb.setRGB(lumScaled, lumScaled, lumScaled); return; } // Chromatic case... // var dQ:Number = (hsl.Luminance < 0.5) ? (hsl.Luminance * (1.0 + hsl.Saturation)): ((hsl.Luminance + hsl.Saturation) - (hsl.Luminance * hsl.Saturation)); var dP:Number = (2.0 * hsl.Luminance) - dQ; var dHueAng:Number = hsl.Hue / 360.0; var dFactor:Number = 1.0 / 3.0; var adT:Array = []; adT[0] = dHueAng + dFactor; // Tr adT[1] = dHueAng; // Tg adT[2] = dHueAng - dFactor; // Tb for (var i:int = 0; i < 3; i++) { if (adT[i] < 0) { adT[i] += 1.0; } if (adT[i] > 1) { adT[i] -= 1.0; } if ((adT[i] * 6) < 1) { adT[i] = dP + ((dQ - dP) * 6.0 * adT[i]); } else if ((adT[i] * 2.0) < 1) // (1.0 / 6.0) <= adT[i] && adT[i] < 0.5 { adT[i] = dQ; } else if ((adT[i] * 3.0) < 2) // 0.5 <= adT[i] && adT[i] < (2.0 / 3.0) { adT[i] = dP + (dQ-dP) * ((2.0/3.0) - adT[i]) * 6.0; } else { adT[i] = dP; } } rgb.setRGB(adT[0] * 255.0, adT[1] * 255.0, adT[2] * 255.0); } // hslToRgb //--------------------------------------- // Adjust the luminance value by the specified factor. // static public function adjustRgbLuminance(rgb:ColorRGB, factor:Number):void { var hsl:ColorHSL = new ColorHSL(); rgbToHsl(hsl, rgb); hsl.Luminance *= factor; if (hsl.Luminance < 0.0) { hsl.Luminance = 0.0; } if (hsl.Luminance > 1.0) { hsl.Luminance = 1.0; } hslToRgb(rgb, hsl); } //--------------------------------------- // static public function uintTo2DigitHex(value:uint):String { var str:String = value.toString(16).toUpperCase(); if (1 == str.length) { str = "0" + str; } return str; } //--------------------------------------- // static public function uintTo6DigitHex(value:uint):String { var str:String = value.toString(16).toUpperCase(); if (1 == str.length) {return "00000" + str;} if (2 == str.length) {return "0000" + str;} if (3 == str.length) {return "000" + str;} if (4 == str.length) {return "00" + str;} if (5 == str.length) {return "0" + str;} return str; } }