/// <summary>
        /// This method creates gradien color with brightnes.
        /// </summary>
        /// <param name="beginColor">Start color for gradient.</param>
        /// <param name="position">Position used between Start and end color.</param>
        /// <returns>Calculated Gradient color from gradient position</returns>
        private Color GetBrightGradientColor(Color beginColor, double position)
        {
            position = position * 2;
            double brightness = 0.5;

            if (position < brightness)
            {
                return(ChartGraphics.GetGradientColor(Color.FromArgb(beginColor.A, 255, 255, 255), beginColor, 1 - brightness + position));
            }
            else if (-brightness + position < 1)
            {
                return(ChartGraphics.GetGradientColor(beginColor, Color.Black, -brightness + position));
            }
            else
            {
                return(Color.FromArgb(beginColor.A, 0, 0, 0));
            }
        }
        /// <summary>
        /// Return intensity of lightStyle for Polygons. There are tree types of lights: None,
        /// Simplistic and Realistic. None Style have same lightStyle intensity on
        /// all polygons. Normal vector doesn’t have influence on this type
        /// of lighting. Simplistic style have lightStyle source, which is
        /// rotated together with scene. Realistic lighting have fixed lightStyle
        /// source and intensity of lightStyle is change when scene is rotated.
        /// </summary>
        /// <param name="points">Points of the polygon</param>
        /// <param name="surfaceColor">Color used for polygons without lighting</param>
        /// <param name="visiblePolygon">This flag gets information if  polygon is visible or not.</param>
        /// <param name="rotation">Y angle ( from -90 to 90 ) Should be used width switchSeriesOrder to get from -180 to 180</param>
        /// <param name="surfaceName">Used for lighting of front - back and left - right sides</param>
        /// <param name="switchSeriesOrder">Used to calculate real y angle</param>
        /// <returns>Color corrected with intensity of lightStyle</returns>
        internal Color GetPolygonLight(Point3D[] points, Color surfaceColor, bool visiblePolygon, float rotation, SurfaceNames surfaceName, bool switchSeriesOrder)
        {
            // Corrected color
            Color color = surfaceColor;

            // Direction of lightStyle source
            Point3D lightSource;

            lightSource = new Point3D(0F, 0F, 1F);

            // There are tree different lightStyle styles: None, Simplistic and realistic.
            switch (_lightStyle)
            {
            // LightStyle style is None
            case  LightStyle.None:
            {
                // Use same color
                break;
            }

            // LightStyle style is Simplistic
            case  LightStyle.Simplistic:
            {
                // Find two vectors of polygon
                Point3D firstVector = new Point3D();
                firstVector.X = points[0].X - points[1].X;
                firstVector.Y = points[0].Y - points[1].Y;
                firstVector.Z = points[0].Z - points[1].Z;

                Point3D secondVector = new Point3D();
                secondVector.X = points[2].X - points[1].X;
                secondVector.Y = points[2].Y - points[1].Y;
                secondVector.Z = points[2].Z - points[1].Z;

                // Find Normal vector for Polygon
                Point3D normalVector = new Point3D();
                normalVector.X = firstVector.Y * secondVector.Z - firstVector.Z * secondVector.Y;
                normalVector.Y = firstVector.Z * secondVector.X - firstVector.X * secondVector.Z;
                normalVector.Z = firstVector.X * secondVector.Y - firstVector.Y * secondVector.X;

                // Polygon is left side ( like side of area chart )
                if (surfaceName == SurfaceNames.Left)
                {
                    color = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.15);
                }
                // Polygon is right side ( like side of area chart )
                else if (surfaceName == SurfaceNames.Right)
                {
                    color = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.15);
                }
                // Polygon is front side ( like side of area chart )
                else if (surfaceName == SurfaceNames.Front)
                {
                    color = surfaceColor;
                }
                // Polygon is back side ( like side of area chart )
                else if (surfaceName == SurfaceNames.Back)
                {
                    color = surfaceColor;
                }
                // Polygon has angle with bottom side ( Line chart or top of area chart )
                else
                {
                    float angleLeft;
                    float angleRight;

                    // Find angles between lightStyle and polygon for different y-axis angles.
                    if (switchSeriesOrder)
                    {
                        if (rotation > 0 && rotation <= 90)
                        {
                            angleLeft  = GetAngle(normalVector, _lightVectors[3]);
                            angleRight = GetAngle(normalVector, _lightVectors[4]);
                        }
                        else
                        {
                            angleLeft  = GetAngle(normalVector, _lightVectors[4]);
                            angleRight = GetAngle(normalVector, _lightVectors[3]);
                        }
                    }
                    else
                    {
                        if (rotation > 0 && rotation <= 90)
                        {
                            angleLeft  = GetAngle(normalVector, _lightVectors[4]);
                            angleRight = GetAngle(normalVector, _lightVectors[3]);
                        }
                        else
                        {
                            angleLeft  = GetAngle(normalVector, _lightVectors[3]);
                            angleRight = GetAngle(normalVector, _lightVectors[4]);
                        }
                    }

                    if (Math.Abs(angleLeft - angleRight) < 0.01)
                    {
                        color = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.25);
                    }
                    else if (angleLeft < angleRight)
                    {
                        color = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.25);
                    }
                    else
                    {
                        color = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.15);
                    }
                }

                break;
            }

            // LightStyle style is Realistic
            default:
            {
                // Find two vectors of polygon
                Point3D firstVector = new Point3D();
                firstVector.X = points[0].X - points[1].X;
                firstVector.Y = points[0].Y - points[1].Y;
                firstVector.Z = points[0].Z - points[1].Z;

                Point3D secondVector = new Point3D();
                secondVector.X = points[2].X - points[1].X;
                secondVector.Y = points[2].Y - points[1].Y;
                secondVector.Z = points[2].Z - points[1].Z;

                // Find Normal vector for Polygon
                Point3D normalVector = new Point3D();
                normalVector.X = firstVector.Y * secondVector.Z - firstVector.Z * secondVector.Y;
                normalVector.Y = firstVector.Z * secondVector.X - firstVector.X * secondVector.Z;
                normalVector.Z = firstVector.X * secondVector.Y - firstVector.Y * secondVector.X;

                // ******************************************************************
                // Color correction. Angle between Normal vector of polygon and
                // vector of lightStyle source is used.
                // ******************************************************************
                if (surfaceName == SurfaceNames.Front)
                {
                    lightSource.Z *= -1;
                    color          = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[2]) / Math.PI);
                }
                else if (surfaceName == SurfaceNames.Back)
                {
                    lightSource.Z *= -1;
                    color          = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[1]) / Math.PI);
                }
                else
                {
                    if (visiblePolygon)
                    {
                        lightSource.Z *= -1;
                    }

                    color = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, normalVector) / Math.PI);
                }

                break;
            }
            }
            return(color);
        }
        /// <summary>
        /// Return intensity of lightStyle for 3D Cube. There are tree types of lights: None,
        /// Simplistic and Realistic. None Style have same lightStyle intensity on
        /// all polygons. Normal vector doesn’t have influence on this type
        /// of lighting. Simplistic style have lightStyle source, which is
        /// rotated together with scene. Realistic lighting have fixed lightStyle
        /// source and intensity of lightStyle is change when scene is rotated.
        /// </summary>
        /// <param name="surfaceColor">Color used for polygons without lighting</param>
        /// <param name="front">Color corrected with intensity of lightStyle for Front side of the 3D Rectangle</param>
        /// <param name="back">Color corrected with intensity of lightStyle for Back side of the 3D Rectangle</param>
        /// <param name="left">Color corrected with intensity of lightStyle for Left side of the 3D Rectangle</param>
        /// <param name="right">Color corrected with intensity of lightStyle for Right side of the 3D Rectangle</param>
        /// <param name="top">Color corrected with intensity of lightStyle for Top side of the 3D Rectangle</param>
        /// <param name="bottom">Color corrected with intensity of lightStyle for Bottom side of the 3D Rectangle</param>
        internal void GetLight(Color surfaceColor, out Color front, out Color back, out Color left, out Color right, out Color top, out Color bottom)
        {
            switch (_lightStyle)
            {
            // LightStyle style is None
            case  LightStyle.None:
            {
                front  = surfaceColor;
                left   = surfaceColor;
                top    = surfaceColor;
                back   = surfaceColor;
                right  = surfaceColor;
                bottom = surfaceColor;
                break;
            }

            // LightStyle style is Simplistic
            case  LightStyle.Simplistic:
            {
                front  = surfaceColor;
                left   = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.25);
                top    = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.15);
                back   = surfaceColor;
                right  = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.25);
                bottom = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.15);
                break;
            }

            // LightStyle style is Realistic
            default:
            {
                // For Right Axis angle Realistic lightStyle should be different
                if (_rightAngleAxis)
                {
                    // LightStyle source Vector
                    Point3D    lightSource   = new Point3D(0F, 0F, -1F);
                    Point3D [] rightPRpoints = new Point3D[1];
                    rightPRpoints[0] = lightSource;
                    RightAngleProjection(rightPRpoints);

                    // ******************************************************************
                    // Color correction. Angle between Normal vector of polygon and
                    // vector of lightStyle source is used.
                    // ******************************************************************
                    if (this._angleY >= 45 || this._angleY <= -45)
                    {
                        front = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[1]) / Math.PI);

                        back = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[2]) / Math.PI);

                        left = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0);

                        right = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0);
                    }
                    else
                    {
                        front = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0);

                        back = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 1);

                        left = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[3]) / Math.PI);

                        right = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[4]) / Math.PI);
                    }

                    top = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[5]) / Math.PI);

                    bottom = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[6]) / Math.PI);
                }
                else
                {
                    // LightStyle source Vector
                    Point3D lightSource = new Point3D(0F, 0F, 1F);

                    // ******************************************************************
                    // Color correction. Angle between Normal vector of polygon and
                    // vector of lightStyle source is used.
                    // ******************************************************************
                    front = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[1]) / Math.PI);

                    back = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[2]) / Math.PI);

                    left = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[3]) / Math.PI);

                    right = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[4]) / Math.PI);

                    top = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[5]) / Math.PI);

                    bottom = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[6]) / Math.PI);
                }

                break;
            }
            }
        }
        /// <summary>
        /// Draws text in specified rectangle.
        /// </summary>
        /// <param name="graphics">Chart graphics.</param>
        /// <param name="textPosition">Text position.</param>
        /// <param name="noSpacingForCenteredText">True if text allowed to be outside of position when centered.</param>
        /// <param name="getTextPosition">True if position text must be returned by the method.</param>
        /// <returns>Text actual position if required.</returns>
        internal RectangleF DrawText(ChartGraphics graphics, RectangleF textPosition, bool noSpacingForCenteredText, bool getTextPosition)
        {
            RectangleF textActualPosition = RectangleF.Empty;

            //***************************************************************
            //** Adjust text position uing text spacing
            //***************************************************************
            bool       annotationRelative = false;
            RectangleF textSpacing        = GetTextSpacing(out annotationRelative);
            float      spacingScaleX      = 1f;
            float      spacingScaleY      = 1f;

            if (annotationRelative)
            {
                if (textPosition.Width > 25f)
                {
                    spacingScaleX = textPosition.Width / 50f;
                    spacingScaleX = Math.Max(1f, spacingScaleX);
                }
                if (textPosition.Height > 25f)
                {
                    spacingScaleY = textPosition.Height / 50f;
                    spacingScaleY = Math.Max(1f, spacingScaleY);
                }
            }

            RectangleF textPositionWithSpacing = new RectangleF(textPosition.Location, textPosition.Size);

            textPositionWithSpacing.Width  -= (textSpacing.Width + textSpacing.X) * spacingScaleX;
            textPositionWithSpacing.X      += textSpacing.X * spacingScaleX;
            textPositionWithSpacing.Height -= (textSpacing.Height + textSpacing.Y) * spacingScaleY;
            textPositionWithSpacing.Y      += textSpacing.Y * spacingScaleY;

            //***************************************************************
            //** Replace new line characters
            //***************************************************************
            string titleText = this.ReplaceKeywords(this.Text.Replace("\\n", "\n"));

            //***************************************************************
            //** Check if centered text require spacing.
            //** Use only half of the spacing required.
            //** Apply only for 1 line of text.
            //***************************************************************
            if (noSpacingForCenteredText &&
                titleText.IndexOf('\n') == -1)
            {
                if (this.Alignment == ContentAlignment.MiddleCenter ||
                    this.Alignment == ContentAlignment.MiddleLeft ||
                    this.Alignment == ContentAlignment.MiddleRight)
                {
                    textPositionWithSpacing.Y       = textPosition.Y;
                    textPositionWithSpacing.Height  = textPosition.Height;
                    textPositionWithSpacing.Height -= textSpacing.Height / 2f + textSpacing.Y / 2f;
                    textPositionWithSpacing.Y      += textSpacing.Y / 2f;
                }
                if (this.Alignment == ContentAlignment.BottomCenter ||
                    this.Alignment == ContentAlignment.MiddleCenter ||
                    this.Alignment == ContentAlignment.TopCenter)
                {
                    textPositionWithSpacing.X      = textPosition.X;
                    textPositionWithSpacing.Width  = textPosition.Width;
                    textPositionWithSpacing.Width -= textSpacing.Width / 2f + textSpacing.X / 2f;
                    textPositionWithSpacing.X     += textSpacing.X / 2f;
                }
            }

            // Draw text
            using (Brush textBrush = new SolidBrush(this.ForeColor))
            {
                using (StringFormat format = new StringFormat(StringFormat.GenericTypographic))
                {
                    //***************************************************************
                    //** Set text format
                    //***************************************************************
                    format.FormatFlags = format.FormatFlags ^ StringFormatFlags.LineLimit;
                    format.Trimming    = StringTrimming.EllipsisCharacter;
                    if (this.Alignment == ContentAlignment.BottomRight ||
                        this.Alignment == ContentAlignment.MiddleRight ||
                        this.Alignment == ContentAlignment.TopRight)
                    {
                        format.Alignment = StringAlignment.Far;
                    }
                    if (this.Alignment == ContentAlignment.BottomCenter ||
                        this.Alignment == ContentAlignment.MiddleCenter ||
                        this.Alignment == ContentAlignment.TopCenter)
                    {
                        format.Alignment = StringAlignment.Center;
                    }
                    if (this.Alignment == ContentAlignment.BottomCenter ||
                        this.Alignment == ContentAlignment.BottomLeft ||
                        this.Alignment == ContentAlignment.BottomRight)
                    {
                        format.LineAlignment = StringAlignment.Far;
                    }
                    if (this.Alignment == ContentAlignment.MiddleCenter ||
                        this.Alignment == ContentAlignment.MiddleLeft ||
                        this.Alignment == ContentAlignment.MiddleRight)
                    {
                        format.LineAlignment = StringAlignment.Center;
                    }

                    //***************************************************************
                    //** Set shadow color and offset
                    //***************************************************************
                    Color     textShadowColor  = ChartGraphics.GetGradientColor(this.ForeColor, Color.Black, 0.8);
                    int       textShadowOffset = 1;
                    TextStyle textStyle        = this.TextStyle;
                    if (textStyle == TextStyle.Shadow &&
                        ShadowOffset != 0)
                    {
                        // Draw shadowed text
                        textShadowColor  = ShadowColor;
                        textShadowOffset = ShadowOffset;
                    }

                    if (textStyle == TextStyle.Shadow)
                    {
                        textShadowColor = (textShadowColor.A != 255) ? textShadowColor : Color.FromArgb(textShadowColor.A / 2, textShadowColor);
                    }

                    //***************************************************************
                    //** Get text actual position
                    //***************************************************************
                    if (getTextPosition)
                    {
                        // Measure text size
                        SizeF textSize = graphics.MeasureStringRel(
                            this.ReplaceKeywords(_text.Replace("\\n", "\n")),
                            this.Font,
                            textPositionWithSpacing.Size,
                            format);

                        // Get text position
                        textActualPosition = new RectangleF(textPositionWithSpacing.Location, textSize);
                        if (this.Alignment == ContentAlignment.BottomRight ||
                            this.Alignment == ContentAlignment.MiddleRight ||
                            this.Alignment == ContentAlignment.TopRight)
                        {
                            textActualPosition.X += textPositionWithSpacing.Width - textSize.Width;
                        }
                        if (this.Alignment == ContentAlignment.BottomCenter ||
                            this.Alignment == ContentAlignment.MiddleCenter ||
                            this.Alignment == ContentAlignment.TopCenter)
                        {
                            textActualPosition.X += (textPositionWithSpacing.Width - textSize.Width) / 2f;
                        }
                        if (this.Alignment == ContentAlignment.BottomCenter ||
                            this.Alignment == ContentAlignment.BottomLeft ||
                            this.Alignment == ContentAlignment.BottomRight)
                        {
                            textActualPosition.Y += textPositionWithSpacing.Height - textSize.Height;
                        }
                        if (this.Alignment == ContentAlignment.MiddleCenter ||
                            this.Alignment == ContentAlignment.MiddleLeft ||
                            this.Alignment == ContentAlignment.MiddleRight)
                        {
                            textActualPosition.Y += (textPositionWithSpacing.Height - textSize.Height) / 2f;
                        }

                        // Do not allow text to go outside annotation position
                        textActualPosition.Intersect(textPositionWithSpacing);
                    }

                    RectangleF absPosition = graphics.GetAbsoluteRectangle(textPositionWithSpacing);
                    Title.DrawStringWithStyle(
                        graphics,
                        titleText,
                        this.TextStyle,
                        this.Font,
                        absPosition,
                        this.ForeColor,
                        textShadowColor,
                        textShadowOffset,
                        format,
                        TextOrientation.Auto
                        );
                }
            }

            return(textActualPosition);
        }