/// <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); }