/// <param name="paletteCount">Min 3.</param>
        public ColorGenerator(int paletteCount)
        {
            if (paletteCount < 3)
                return;

            // generate at least as many colors that we need
            const double exponent = 3;

            double a = Math.Pow(paletteCount, 1 / exponent);
            double @base = Math.Ceiling(a);
            double max = Math.Pow(@base, exponent);

            for (int i = 0; i < max; i++)
            {
                double red = Math.Floor(i / (@base * @base))
                    / (@base - 1);
                double yellow = Math.Floor((i / @base) % @base)
                    / (@base - 1);
                double blue = Math.Floor(i % @base)
                    / (@base - 1);

                RybColor color = new RybColor(red, yellow, blue);
                m_colorPalette.Add(color);
            }

            m_picked = null;
        }
        /// <summary>
        /// Euclidian distance
        /// </summary>
        public static double DistanceSquared(RybColor color, RybColor other)
        {
            double redDistance = Math.Pow(color.Red - other.Red, 2);
            double yellowDistance = Math.Pow(color.Yellow - other.Yellow, 2);
            double blueDistance = Math.Pow(color.Blue - other.Blue, 2);

            return redDistance + yellowDistance + blueDistance;
        }
        public static Color ToColor(RybColor rybColor)
        {
            Color color = new Color()
            {
                A = 255,
                R = (byte)GetRed(rybColor),
                G = (byte)GetGreen(rybColor),
                B = (byte)GetBlue(rybColor),
            };

            return color;
        }
        private static double GetRed(RybColor rybColor)
        {
            var iR = rybColor.Red;
            var iY = rybColor.Yellow;
            var iB = rybColor.Blue;

            var x0 = CubicInterpolate(iB, 1.0, 0.163);
            var x1 = CubicInterpolate(iB, 1.0, 0.0);
            var x2 = CubicInterpolate(iB, 1.0, 0.5);
            var x3 = CubicInterpolate(iB, 1.0, 0.2);
            var y0 = CubicInterpolate(iY, x0, x1);
            var y1 = CubicInterpolate(iY, x2, x3);
            return Math.Ceiling(255 * CubicInterpolate(iR, y0, y1));
        }
        public RybColor PickNextColor()
        {
            if (m_picked == null)
            {
                m_picked = m_colorPalette.FirstOrDefault();
                if (m_picked == null)
                    return null;

                m_colorPalette.RemoveAt(0);
                Debug.WriteLine("Initial color is {0}", m_picked);
                m_pickedColorCount = 1;
                return m_picked;
            }

            // pick (close to) the color that is farthest away from the last picked color
            var result = m_colorPalette.Aggregate<RybColor,Tuple<RybColor, double>>(
                Tuple.Create(m_colorPalette[0], DistanceFromLastPickedColor(m_colorPalette[0])),
                (acc, color) =>
                {
                    var currentDistance = DistanceFromLastPickedColor(color);
                    if (acc.Item2 < currentDistance)
                        return Tuple.Create(color, currentDistance);
                    else
                        return acc;
                });

            m_colorPalette.Remove(result.Item1);

            var pick = result.Item1;
            m_picked = new RybColor(
                (m_pickedColorCount * m_picked.Red + pick.Red)
                    / (m_pickedColorCount + 1),
                (m_pickedColorCount * m_picked.Yellow + pick.Yellow)
                    / (m_pickedColorCount + 1),
                (m_pickedColorCount * m_picked.Blue + pick.Blue)
                    / (m_pickedColorCount + 1));

            m_pickedColorCount++;

            System.Diagnostics.Debug.WriteLine("Farthest color is " + pick.ToString());
            return pick;
        }
 private double DistanceFromLastPickedColor(RybColor color)
 {
     return RybColor.DistanceSquared(color, m_picked);
 }