private void UpdateEllipse()

in src/Avalonia.Controls.ColorPicker/ColorSpectrum/ColorSpectrum.cs [797:980]


        private void UpdateEllipse()
        {
            if (_selectionEllipsePanel == null)
            {
                return;
            }

            // If we don't have an image size yet, we shouldn't be showing the ellipse.
            if (_imageWidthFromLastBitmapCreation == 0 ||
                _imageHeightFromLastBitmapCreation == 0)
            {
                _selectionEllipsePanel.IsVisible = false;
                return;
            }
            else
            {
                _selectionEllipsePanel.IsVisible = true;
            }

            double xPosition;
            double yPosition;

            Hsv hsvColor = new Hsv(HsvColor);

            hsvColor.H = MathUtilities.Clamp(hsvColor.H, (double)_minHueFromLastBitmapCreation, (double)_maxHueFromLastBitmapCreation);
            hsvColor.S = MathUtilities.Clamp(hsvColor.S, _minSaturationFromLastBitmapCreation / 100.0, _maxSaturationFromLastBitmapCreation / 100.0);
            hsvColor.V = MathUtilities.Clamp(hsvColor.V, _minValueFromLastBitmapCreation / 100.0, _maxValueFromLastBitmapCreation / 100.0);

            if (_shapeFromLastBitmapCreation == ColorSpectrumShape.Box)
            {
                double xPercent = 0;
                double yPercent = 0;

                double hPercent = (hsvColor.H - _minHueFromLastBitmapCreation) / (_maxHueFromLastBitmapCreation - _minHueFromLastBitmapCreation);
                double sPercent = (hsvColor.S * 100.0 - _minSaturationFromLastBitmapCreation) / (_maxSaturationFromLastBitmapCreation - _minSaturationFromLastBitmapCreation);
                double vPercent = (hsvColor.V * 100.0 - _minValueFromLastBitmapCreation) / (_maxValueFromLastBitmapCreation - _minValueFromLastBitmapCreation);

                // In the case where saturation was an axis in the spectrum with hue, or value is an axis, full stop,
                // we inverted the direction of that axis in order to put more hue on the outside of the ring,
                // so we need to do similarly here when positioning the ellipse.
                if (_componentsFromLastBitmapCreation == ColorSpectrumComponents.HueSaturation ||
                    _componentsFromLastBitmapCreation == ColorSpectrumComponents.SaturationHue)
                {
                    sPercent = 1 - sPercent;
                }
                else
                {
                    vPercent = 1 - vPercent;
                }

                switch (_componentsFromLastBitmapCreation)
                {
                    case ColorSpectrumComponents.HueValue:
                        xPercent = hPercent;
                        yPercent = vPercent;
                        break;

                    case ColorSpectrumComponents.HueSaturation:
                        xPercent = hPercent;
                        yPercent = sPercent;
                        break;

                    case ColorSpectrumComponents.ValueHue:
                        xPercent = vPercent;
                        yPercent = hPercent;
                        break;

                    case ColorSpectrumComponents.ValueSaturation:
                        xPercent = vPercent;
                        yPercent = sPercent;
                        break;

                    case ColorSpectrumComponents.SaturationHue:
                        xPercent = sPercent;
                        yPercent = hPercent;
                        break;

                    case ColorSpectrumComponents.SaturationValue:
                        xPercent = sPercent;
                        yPercent = vPercent;
                        break;
                }

                xPosition = _imageWidthFromLastBitmapCreation * xPercent;
                yPosition = _imageHeightFromLastBitmapCreation * yPercent;
            }
            else
            {
                double thetaValue = 0;
                double rValue = 0;

                double hThetaValue =
                    _maxHueFromLastBitmapCreation != _minHueFromLastBitmapCreation ?
                    360 * (hsvColor.H - _minHueFromLastBitmapCreation) / (_maxHueFromLastBitmapCreation - _minHueFromLastBitmapCreation) :
                    0;
                double sThetaValue =
                    _maxSaturationFromLastBitmapCreation != _minSaturationFromLastBitmapCreation ?
                    360 * (hsvColor.S * 100.0 - _minSaturationFromLastBitmapCreation) / (_maxSaturationFromLastBitmapCreation - _minSaturationFromLastBitmapCreation) :
                    0;
                double vThetaValue =
                    _maxValueFromLastBitmapCreation != _minValueFromLastBitmapCreation ?
                    360 * (hsvColor.V * 100.0 - _minValueFromLastBitmapCreation) / (_maxValueFromLastBitmapCreation - _minValueFromLastBitmapCreation) :
                    0;
                double hRValue = _maxHueFromLastBitmapCreation != _minHueFromLastBitmapCreation ?
                    (hsvColor.H - _minHueFromLastBitmapCreation) / (_maxHueFromLastBitmapCreation - _minHueFromLastBitmapCreation) - 1 :
                    0;
                double sRValue = _maxSaturationFromLastBitmapCreation != _minSaturationFromLastBitmapCreation ?
                    (hsvColor.S * 100.0 - _minSaturationFromLastBitmapCreation) / (_maxSaturationFromLastBitmapCreation - _minSaturationFromLastBitmapCreation) - 1 :
                    0;
                double vRValue = _maxValueFromLastBitmapCreation != _minValueFromLastBitmapCreation ?
                    (hsvColor.V * 100.0 - _minValueFromLastBitmapCreation) / (_maxValueFromLastBitmapCreation - _minValueFromLastBitmapCreation) - 1 :
                    0;

                // In the case where saturation was an axis in the spectrum with hue, or value is an axis, full stop,
                // we inverted the direction of that axis in order to put more hue on the outside of the ring,
                // so we need to do similarly here when positioning the ellipse.
                if (_componentsFromLastBitmapCreation == ColorSpectrumComponents.HueSaturation ||
                    _componentsFromLastBitmapCreation == ColorSpectrumComponents.SaturationHue)
                {
                    sThetaValue = 360 - sThetaValue;
                    sRValue = -sRValue - 1;
                }
                else
                {
                    vThetaValue = 360 - vThetaValue;
                    vRValue = -vRValue - 1;
                }

                switch (_componentsFromLastBitmapCreation)
                {
                    case ColorSpectrumComponents.HueValue:
                        thetaValue = hThetaValue;
                        rValue = vRValue;
                        break;

                    case ColorSpectrumComponents.HueSaturation:
                        thetaValue = hThetaValue;
                        rValue = sRValue;
                        break;

                    case ColorSpectrumComponents.ValueHue:
                        thetaValue = vThetaValue;
                        rValue = hRValue;
                        break;

                    case ColorSpectrumComponents.ValueSaturation:
                        thetaValue = vThetaValue;
                        rValue = sRValue;
                        break;

                    case ColorSpectrumComponents.SaturationHue:
                        thetaValue = sThetaValue;
                        rValue = hRValue;
                        break;

                    case ColorSpectrumComponents.SaturationValue:
                        thetaValue = sThetaValue;
                        rValue = vRValue;
                        break;
                }

                double radius = Math.Min(_imageWidthFromLastBitmapCreation, _imageHeightFromLastBitmapCreation) / 2;

                xPosition = (Math.Cos((thetaValue * Math.PI / 180.0) + Math.PI) * radius * rValue) + radius;
                yPosition = (Math.Sin((thetaValue * Math.PI / 180.0) + Math.PI) * radius * rValue) + radius;
            }

            // Remember the bitmap size follows physical device pixels
            // Warning: LayoutHelper.GetLayoutScale() doesn't work unless the control is visible
            // This will not be true in all cases if the color is updated from another control or code-behind
            var scale = LayoutHelper.GetLayoutScale(this);
            Canvas.SetLeft(_selectionEllipsePanel, (xPosition / scale) - (_selectionEllipsePanel.Width / 2));
            Canvas.SetTop(_selectionEllipsePanel, (yPosition / scale) - (_selectionEllipsePanel.Height / 2));

            // We only want to bother with the color name tool tip if we can provide color names.
            if (IsFocused &&
                _selectionEllipsePanel != null &&
                ColorHelper.ToDisplayNameExists)
            {
                ToolTip.SetIsOpen(_selectionEllipsePanel, true);
            }

            UpdatePseudoClasses();
        }