private static Color Mix(WeightedValue<Color>[] colors)
        {
            double weightSum = colors.Select(vv => vv.Weight).Sum();

            var normalizedHSLColors = colors.Select(vc => new WeightedValue<HSL>(ColorSpaceHelper.RGBtoHSL(vc.Value.R, vc.Value.G, vc.Value.B), vc.Weight / weightSum));

            double h = 0.0;
            double count = 0.0;
            double sSum = 0.0;
            double lSum = 0.0;
            double x = 0.0;
            double y = 0.0;

            foreach (var color in normalizedHSLColors)
            {
                count++;
                sSum += color.Value.Saturation * (color.Weight * 2.0);
                lSum += color.Value.Luminance * (color.Weight * 2.0);
                x += Math.Cos(2.0 * Math.PI * (DegreeToPercent(color.Value.Hue) * (color.Weight * 2.0)));
                y += Math.Sin(2.0 * Math.PI * (DegreeToPercent(color.Value.Hue) * (color.Weight * 2.0)));
            }

            double s = sSum / count;
            double l = lSum / count;

            if ((x != 0.0) || (y != 0.0))
            {
                h = Math.Atan2(y, x) / (2.0 * Math.PI);
            }
            else
            {
                s = 0.0;
            }

            var result = ColorSpaceHelper.HSLtoRGB(PercentToDegree(h), s, l);

            double r = result.Red, g = result.Green, b = result.Blue;

            const double addRatio = 0.0;
            const double avgRatio = 0.0;
            const double subRatio = 0.0;
            const double colorizeRatio = (1.0 - (addRatio + avgRatio + subRatio));

            double additiveR = ComputeAdditiveComponent(colors, weightSum, (c) => c.R);
            double substractiveR = ComputeSubtractiveComponent(colors, weightSum, (c) => c.R);
            double avgR = ComputeAvgComponent(colors, weightSum, (c) => c.R);

            double additiveG = ComputeAdditiveComponent(colors, weightSum, (c) => c.G);
            double substractiveG = ComputeSubtractiveComponent(colors, weightSum, (c) => c.G);
            double avgG = ComputeAvgComponent(colors, weightSum, (c) => c.G);

            double additiveB = ComputeAdditiveComponent(colors, weightSum, (c) => c.B);
            double substractiveB = ComputeSubtractiveComponent(colors, weightSum, (c) => c.B);
            double avgB = ComputeAvgComponent(colors, weightSum, (c) => c.B);

            return Color.FromRgb(
                ToByte(r * colorizeRatio + additiveR * addRatio + substractiveR * subRatio + avgR * avgRatio),
                ToByte(g * colorizeRatio + additiveG * addRatio + substractiveG * subRatio + avgG * avgRatio),
                ToByte(b * colorizeRatio + additiveB * addRatio + substractiveB * subRatio + avgB * avgRatio));
        }
 private static double ComputeAdditiveComponent(WeightedValue<Color>[] colors, double weightSum, Func<Color, byte> selectComponent)
 {
     return ToByteRange(Add(colors.Select(c => new WeightedValue<double>(selectComponent(c.Value), c.Weight / weightSum))));
 }
 private static double ComputeAvgComponent(WeightedValue<Color>[] colors, double weightSum, Func<Color, byte> selectComponent)
 {
     return ToByteRange(colors.Select(c => selectComponent(c.Value) * ((c.Weight / weightSum) * 2.0)).Average());
 }