public static SphereDataView Create(SphereData originalSphereData, Rect3D displayedDataBounds, double maxTime, Size locationBounds, double maxSize)
        {
            // First calculate normalized values (from 0 to 1)
            double x = originalSphereData.Time / maxTime;
            double y = originalSphereData.Location.Y / locationBounds.Height;
            double z = originalSphereData.Location.X / locationBounds.Width;


            // Set color of the sphere based on its y position
            // We choose the color from the gradient defined in EnsureGradientColorsArray
            EnsureGradientColorsArray();

            int   colorArrayIndex = (int)(y * _gradientColorsArray.Length);
            Color color           = _gradientColorsArray[colorArrayIndex];


            // Now put normalized values into a 3D space that is defined by displayedDataBounds
            x = (x * displayedDataBounds.SizeX) + displayedDataBounds.X;
            y = (y * displayedDataBounds.SizeY) + displayedDataBounds.Y;
            z = (z * displayedDataBounds.SizeZ) + displayedDataBounds.Z;

            Point3D position3D = new Point3D(x, y, z);


            // Use Size value to define the sphere radius in a range from 1 to 3
            double sphereRadius = (originalSphereData.Size / maxSize) * 2 + 1;


            // Now we have all the data to create the SphereDataView
            var sphereDataView = new SphereDataView(originalSphereData, position3D, color, sphereRadius);

            return(sphereDataView);
        }
        public SphereDataView(SphereData originalSphereData, Point3D position, Color color, double radius)
        {
            OriginalSphereData = originalSphereData;

            Position = position;
            Color    = color;
            Radius   = radius;

            ScreenPosition = new Point(double.NaN, double.NaN);
        }
        public List <SphereData> InitializeData()
        {
            // originalData will hold our original random data
            var originalData = new List <SphereData>();

            // Start in the middle
            double x = _locationSize.Width / 2;
            double y = _locationSize.Height / 2;

            double randomizationFactor = 0.5; // How much can the data go up and down

            // Add some random data
            for (int i = 0; i < 20; i++)
            {
                // Get random offset
                double dx = _locationSize.Width * randomizationFactor * (_rnd.NextDouble() - 0.5);  //_rnd.NextDouble() * locationSize.Width * randomizationFactor - locationSize.Width * randomizationFactor * 0.5;
                double dy = _locationSize.Height * randomizationFactor * (_rnd.NextDouble() - 0.5); // _rnd.NextDouble() * locationSize.Height * randomizationFactor - locationSize.Height * randomizationFactor * 0.5;

                x += dx;
                y += dy;

                // Prevent going out of limits (0,0 ... locationSize)
                if (x < 0)
                {
                    x = -x;
                }
                else if (x > _locationSize.Width)
                {
                    x = _locationSize.Width - 1 * (x - _locationSize.Width);
                }

                if (y < 0)
                {
                    y = -y;
                }
                else if (y > _locationSize.Height)
                {
                    y = _locationSize.Height - 1 * (y - _locationSize.Height);
                }

                double power = _rnd.NextDouble() * _maxSize;

                var sphereData = new SphereData(i, new Point(x, y), power);
                originalData.Add(sphereData);

                //System.Diagnostics.Debug.WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "originalData.Add(new SphereData({0}, new Point({1:0}, {2:0}), {3:0.00}));", i, x, y, power));
            }

            return(originalData);
        }