private void FillPixelForRing()

in src/Avalonia.Controls.ColorPicker/ColorSpectrum/ColorSpectrum.cs [1393:1577]


        private void FillPixelForRing(
            double x,
            double y,
            double radius,
            Hsv baseHsv,
            ColorSpectrumComponents components,
            double minHue,
            double maxHue,
            double minSaturation,
            double maxSaturation,
            double minValue,
            double maxValue,
            PooledList<byte> bgraMinPixelData,
            PooledList<byte> bgraMiddle1PixelData,
            PooledList<byte> bgraMiddle2PixelData,
            PooledList<byte> bgraMiddle3PixelData,
            PooledList<byte> bgraMiddle4PixelData,
            PooledList<byte> bgraMaxPixelData,
            List<Hsv> newHsvValues)
        {
            double hMin = minHue;
            double hMax = maxHue;
            double sMin = minSaturation / 100.0;
            double sMax = maxSaturation / 100.0;
            double vMin = minValue / 100.0;
            double vMax = maxValue / 100.0;

            double distanceFromRadius = Math.Sqrt(Math.Pow(x - radius, 2) + Math.Pow(y - radius, 2));

            double xToUse = x;
            double yToUse = y;

            // If we're outside the ring, then we want the pixel to appear as blank.
            // However, to avoid issues with rounding errors, we'll act as though this point
            // is on the edge of the ring for the purposes of returning an HSL value.
            // That way, hit testing on the edges will always return the correct value.
            if (distanceFromRadius > radius)
            {
                xToUse = (radius / distanceFromRadius) * (x - radius) + radius;
                yToUse = (radius / distanceFromRadius) * (y - radius) + radius;
                distanceFromRadius = radius;
            }

            Hsv hsvMin = baseHsv;
            Hsv hsvMiddle1 = baseHsv;
            Hsv hsvMiddle2 = baseHsv;
            Hsv hsvMiddle3 = baseHsv;
            Hsv hsvMiddle4 = baseHsv;
            Hsv hsvMax = baseHsv;

            double r = 1 - distanceFromRadius / radius;

            double theta = Math.Atan2((radius - yToUse), (radius - xToUse)) * 180.0 / Math.PI;
            theta += 180.0;
            theta = Math.Floor(theta);

            while (theta > 360)
            {
                theta -= 360;
            }

            double thetaPercent = theta / 360;

            switch (components)
            {
                case ColorSpectrumComponents.HueValue:
                    hsvMin.H = hsvMiddle1.H = hsvMiddle2.H = hsvMiddle3.H = hsvMiddle4.H = hsvMax.H = hMin + thetaPercent * (hMax - hMin);
                    hsvMin.V = hsvMiddle1.V = hsvMiddle2.V = hsvMiddle3.V = hsvMiddle4.V = hsvMax.V = vMin + r * (vMax - vMin);
                    hsvMin.S = 0;
                    hsvMax.S = 1;
                    break;

                case ColorSpectrumComponents.HueSaturation:
                    hsvMin.H = hsvMiddle1.H = hsvMiddle2.H = hsvMiddle3.H = hsvMiddle4.H = hsvMax.H = hMin + thetaPercent * (hMax - hMin);
                    hsvMin.S = hsvMiddle1.S = hsvMiddle2.S = hsvMiddle3.S = hsvMiddle4.S = hsvMax.S = sMin + r * (sMax - sMin);
                    hsvMin.V = 0;
                    hsvMax.V = 1;
                    break;

                case ColorSpectrumComponents.ValueHue:
                    hsvMin.V = hsvMiddle1.V = hsvMiddle2.V = hsvMiddle3.V = hsvMiddle4.V = hsvMax.V = vMin + thetaPercent * (vMax - vMin);
                    hsvMin.H = hsvMiddle1.H = hsvMiddle2.H = hsvMiddle3.H = hsvMiddle4.H = hsvMax.H = hMin + r * (hMax - hMin);
                    hsvMin.S = 0;
                    hsvMax.S = 1;
                    break;

                case ColorSpectrumComponents.ValueSaturation:
                    hsvMin.V = hsvMiddle1.V = hsvMiddle2.V = hsvMiddle3.V = hsvMiddle4.V = hsvMax.V = vMin + thetaPercent * (vMax - vMin);
                    hsvMin.S = hsvMiddle1.S = hsvMiddle2.S = hsvMiddle3.S = hsvMiddle4.S = hsvMax.S = sMin + r * (sMax - sMin);
                    hsvMin.H = 0;
                    hsvMiddle1.H = 60;
                    hsvMiddle2.H = 120;
                    hsvMiddle3.H = 180;
                    hsvMiddle4.H = 240;
                    hsvMax.H = 300;
                    break;

                case ColorSpectrumComponents.SaturationHue:
                    hsvMin.S = hsvMiddle1.S = hsvMiddle2.S = hsvMiddle3.S = hsvMiddle4.S = hsvMax.S = sMin + thetaPercent * (sMax - sMin);
                    hsvMin.H = hsvMiddle1.H = hsvMiddle2.H = hsvMiddle3.H = hsvMiddle4.H = hsvMax.H = hMin + r * (hMax - hMin);
                    hsvMin.V = 0;
                    hsvMax.V = 1;
                    break;

                case ColorSpectrumComponents.SaturationValue:
                    hsvMin.S = hsvMiddle1.S = hsvMiddle2.S = hsvMiddle3.S = hsvMiddle4.S = hsvMax.S = sMin + thetaPercent * (sMax - sMin);
                    hsvMin.V = hsvMiddle1.V = hsvMiddle2.V = hsvMiddle3.V = hsvMiddle4.V = hsvMax.V = vMin + r * (vMax - vMin);
                    hsvMin.H = 0;
                    hsvMiddle1.H = 60;
                    hsvMiddle2.H = 120;
                    hsvMiddle3.H = 180;
                    hsvMiddle4.H = 240;
                    hsvMax.H = 300;
                    break;
            }

            // If saturation is an axis in the spectrum with hue, or value is an axis, then we want
            // that axis to go from maximum at the top to minimum at the bottom,
            // or maximum at the outside to minimum at the inside in the case of the ring configuration,
            // so we'll invert the number before assigning the HSL value to the array.
            // Otherwise, we'll have a very narrow section in the middle that actually has meaningful hue
            // in the case of the ring configuration.
            if (components == ColorSpectrumComponents.HueSaturation ||
                components == ColorSpectrumComponents.SaturationHue)
            {
                hsvMin.S = sMax - hsvMin.S + sMin;
                hsvMiddle1.S = sMax - hsvMiddle1.S + sMin;
                hsvMiddle2.S = sMax - hsvMiddle2.S + sMin;
                hsvMiddle3.S = sMax - hsvMiddle3.S + sMin;
                hsvMiddle4.S = sMax - hsvMiddle4.S + sMin;
                hsvMax.S = sMax - hsvMax.S + sMin;
            }
            else
            {
                hsvMin.V = vMax - hsvMin.V + vMin;
                hsvMiddle1.V = vMax - hsvMiddle1.V + vMin;
                hsvMiddle2.V = vMax - hsvMiddle2.V + vMin;
                hsvMiddle3.V = vMax - hsvMiddle3.V + vMin;
                hsvMiddle4.V = vMax - hsvMiddle4.V + vMin;
                hsvMax.V = vMax - hsvMax.V + vMin;
            }

            newHsvValues.Add(hsvMin);

            Rgb rgbMin = hsvMin.ToRgb();
            bgraMinPixelData.Add((byte)Math.Round(rgbMin.B * 255)); // b
            bgraMinPixelData.Add((byte)Math.Round(rgbMin.G * 255)); // g
            bgraMinPixelData.Add((byte)Math.Round(rgbMin.R * 255)); // r
            bgraMinPixelData.Add(255); // a

            // We'll only save pixel data for the middle bitmaps if our third dimension is hue.
            if (components == ColorSpectrumComponents.ValueSaturation ||
                components == ColorSpectrumComponents.SaturationValue)
            {
                Rgb rgbMiddle1 = hsvMiddle1.ToRgb();
                bgraMiddle1PixelData.Add((byte)Math.Round(rgbMiddle1.B * 255)); // b
                bgraMiddle1PixelData.Add((byte)Math.Round(rgbMiddle1.G * 255)); // g
                bgraMiddle1PixelData.Add((byte)Math.Round(rgbMiddle1.R * 255)); // r
                bgraMiddle1PixelData.Add(255); // a

                Rgb rgbMiddle2 = hsvMiddle2.ToRgb();
                bgraMiddle2PixelData.Add((byte)Math.Round(rgbMiddle2.B * 255)); // b
                bgraMiddle2PixelData.Add((byte)Math.Round(rgbMiddle2.G * 255)); // g
                bgraMiddle2PixelData.Add((byte)Math.Round(rgbMiddle2.R * 255)); // r
                bgraMiddle2PixelData.Add(255); // a

                Rgb rgbMiddle3 = hsvMiddle3.ToRgb();
                bgraMiddle3PixelData.Add((byte)Math.Round(rgbMiddle3.B * 255)); // b
                bgraMiddle3PixelData.Add((byte)Math.Round(rgbMiddle3.G * 255)); // g
                bgraMiddle3PixelData.Add((byte)Math.Round(rgbMiddle3.R * 255)); // r
                bgraMiddle3PixelData.Add(255); // a

                Rgb rgbMiddle4 = hsvMiddle4.ToRgb();
                bgraMiddle4PixelData.Add((byte)Math.Round(rgbMiddle4.B * 255)); // b
                bgraMiddle4PixelData.Add((byte)Math.Round(rgbMiddle4.G * 255)); // g
                bgraMiddle4PixelData.Add((byte)Math.Round(rgbMiddle4.R * 255)); // r
                bgraMiddle4PixelData.Add(255); // a
            }

            Rgb rgbMax = hsvMax.ToRgb();
            bgraMaxPixelData.Add((byte)Math.Round(rgbMax.B * 255)); // b
            bgraMaxPixelData.Add((byte)Math.Round(rgbMax.G * 255)); // g
            bgraMaxPixelData.Add((byte)Math.Round(rgbMax.R * 255)); // r
            bgraMaxPixelData.Add(255); // a
        }