private Color4[] CreateDistanceColors()
        {
            // Here we prepare list of materials that will be used to for arrows on different distances from the gold sphere

            // We use HeightMapMesh3D.GetGradientColorsArray to create an array with color values created from the gradient. The array size is 30.
            var gradientStopCollection = new GradientStopCollection();

            gradientStopCollection.Add(new GradientStop(Colors.Red, 0));          // uses with min distance - closest to the object
            gradientStopCollection.Add(new GradientStop(Colors.Orange, 0.2));     // uses with min distance - closest to the object
            gradientStopCollection.Add(new GradientStop(Colors.Yellow, 0.4));     // uses with min distance - closest to the object
            gradientStopCollection.Add(new GradientStop(Colors.Green, 0.6));      // uses with min distance - closest to the object
            gradientStopCollection.Add(new GradientStop(Colors.DarkBlue, 0.8));   // used with max distance
            gradientStopCollection.Add(new GradientStop(Colors.DodgerBlue, 1));   // used with max distance

            var linearGradientBrush = new LinearGradientBrush(gradientStopCollection, new Point(0, 0), new Point(0, 1));

            // Use linearGradientBrush to create an array with 128 Colors
            var gradientColorsArray = HeightMapMesh3D.GetGradientColorsArray(linearGradientBrush, 128);

            var gradientColors = new Color4[gradientColorsArray.Length];

            for (int i = 0; i < gradientColorsArray.Length; i++)
            {
                gradientColors[i] = gradientColorsArray[i].ToColor4();
            }

            return(gradientColors);
        }
        private static void EnsureGradientColorsArray()
        {
            // We use HeightMapMesh3D.GetGradientColorsArray to create an array with color values created from the gradient. The array size is 30.
            var gradientStopCollection = new GradientStopCollection();

            gradientStopCollection.Add(new GradientStop(Colors.Yellow, 1));
            gradientStopCollection.Add(new GradientStop(Colors.DodgerBlue, 0));
            var linearGradientBrush = new LinearGradientBrush(gradientStopCollection, new Point(0, 0), new Point(0, 1));

            _gradientColorsArray = HeightMapMesh3D.GetGradientColorsArray(linearGradientBrush, 30);
        }
        public Graph3D()
        {
            InitializeComponent();

            CameraControllerInfo.AddCustomInfoLine(0, Ab3d.Controls.MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed, "Click to select sphere\r\nDrag for rectangular section");


            var linearGradientBrush = CreateGradientBrush();

            _gradientColorsArray = HeightMapMesh3D.GetGradientColorsArray(linearGradientBrush, 30);

            LegendRectangle.Fill = linearGradientBrush;


            _xyDataRange = new Rect(-10, -10, 20, 20);
            _sampleData  = GenerateRandomData(_xyDataRange, relativeMargin: 0.2, dataCount: 20);


            // Setup axis limits and shown values
            AxesBox.SetAxisDataRange(AxesBoxVisual3D.AxisTypes.XAxis, minimumValue: 0, maximumValue: _sampleData.Count, majorTicksStep: 2, minorTicksStep: 0, snapMaximumValueToMajorTicks: true);
            AxesBox.SetAxisDataRange(AxesBoxVisual3D.AxisTypes.YAxis, minimumValue: _xyDataRange.Y, maximumValue: _xyDataRange.Y + _xyDataRange.Height, majorTicksStep: 5, minorTicksStep: 2.5, snapMaximumValueToMajorTicks: true);
            AxesBox.SetAxisDataRange(AxesBoxVisual3D.AxisTypes.ZAxis, minimumValue: _xyDataRange.X, maximumValue: _xyDataRange.X + _xyDataRange.Width, majorTicksStep: 5, minorTicksStep: 2.5, snapMaximumValueToMajorTicks: true);


            // All data will be displayed in a 3D box defined below:
            var displayedDataBounds = new Rect3D(AxesBox.CenterPosition.X - AxesBox.Size.X * 0.5,
                                                 AxesBox.CenterPosition.Y - AxesBox.Size.Y * 0.5,
                                                 AxesBox.CenterPosition.Z - AxesBox.Size.Z * 0.5,
                                                 AxesBox.Size.X,
                                                 AxesBox.Size.Y,
                                                 AxesBox.Size.Z);

            ShowData(_sampleData, displayedDataBounds, _xyDataRange);

            UpdateSelectedSpheresData();

            MinValueTextBlock.Text = string.Format("{0:0}", _xyDataRange.Y);
            MaxValueTextBlock.Text = string.Format("{0:0}", _xyDataRange.Y + _xyDataRange.Height);

            // Subscribe mouse events that will be used to create selection rectangle
            ViewportBorder.MouseLeftButtonDown += SelectionOverlayCanvasOnMouseLeftButtonDown;
            ViewportBorder.MouseMove           += SelectionOverlayCanvasOnMouseMove;
            ViewportBorder.MouseLeftButtonUp   += SelectionOverlayCanvasOnMouseLeftButtonUp;
        }