Beispiel #1
0
        /// <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 static SKColor GetBrightGradientColor(SKColor beginColor, double position)
        {
            position *= 2;
            double brightness = 0.5;

            if (position < brightness)
            {
                return(ChartGraphics.GetGradientColor(Color.FromArgb(beginColor.Alpha, (byte)255, (byte)255, (byte)255), beginColor, 1 - brightness + position));
            }
            else if (-brightness + position < 1)
            {
                return(ChartGraphics.GetGradientColor(beginColor, SKColors.Black, -brightness + position));
            }
            else
            {
                return(Color.FromArgb(beginColor.Alpha, (byte)0, (byte)0, (byte)0));
            }
        }
Beispiel #2
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 SKColor GetPolygonLight(Point3D[] points, SKColor surfaceColor, bool visiblePolygon, float rotation, SurfaceNames surfaceName, bool switchSeriesOrder)
        {
            // Corrected color
            SKColor 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();
                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();
                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();
                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, SKColors.Black, 0.15);
                }
                // Polygon is right side ( like side of area chart )
                else if (surfaceName == SurfaceNames.Right)
                {
                    color = ChartGraphics.GetGradientColor(surfaceColor, SKColors.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, SKColors.Black, 0.25);
                    }
                    else if (angleLeft < angleRight)
                    {
                        color = ChartGraphics.GetGradientColor(surfaceColor, SKColors.Black, 0.25);
                    }
                    else
                    {
                        color = ChartGraphics.GetGradientColor(surfaceColor, SKColors.Black, 0.15);
                    }
                }

                break;
            }

            // LightStyle style is Realistic
            default:
            {
                // Find two vectors of polygon
                Point3D firstVector = new();
                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();
                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();
                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);
        }
Beispiel #3
0
        /// <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(SKColor surfaceColor, out SKColor front, out SKColor back, out SKColor left, out SKColor right, out SKColor top, out SKColor 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, SKColors.Black, 0.25);
                top    = ChartGraphics.GetGradientColor(surfaceColor, SKColors.Black, 0.15);
                back   = surfaceColor;
                right  = ChartGraphics.GetGradientColor(surfaceColor, SKColors.Black, 0.25);
                bottom = ChartGraphics.GetGradientColor(surfaceColor, SKColors.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(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 (_angleY >= 45 || _angleY <= -45)
                    {
                        front = ChartGraphics.GetGradientColor(surfaceColor, SKColors.Black, GetAngle(lightSource, _lightVectors[1]) / Math.PI);

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

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

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

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

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

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

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

                    bottom = ChartGraphics.GetGradientColor(surfaceColor, SKColors.Black, GetAngle(lightSource, _lightVectors[6]) / Math.PI);
                }
                else
                {
                    // LightStyle source Vector
                    Point3D lightSource = new(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;
            }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Draws 3D button in the scroll bar
        /// </summary>
        /// <param name="graph">Chart graphics.</param>
        /// <param name="buttonRect">Button position.</param>
        /// <param name="pressedState">Indicates that button is pressed.</param>
        /// <param name="buttonType">Button type to draw.</param>
        internal void PaintScrollBar3DButton(
            ChartGraphics graph,
            SKRect buttonRect,
            bool pressedState,
            ScrollBarButtonType buttonType)
        {
            // Page Up/Down buttons do not require drawing
            if (buttonType == ScrollBarButtonType.LargeIncrement || buttonType == ScrollBarButtonType.LargeDecrement)
            {
                return;
            }

            // Get 3 levels of colors for button drawing
            var darkerColor  = ChartGraphics.GetGradientColor(_buttonCurrentColor, SKColors.Black, 0.5);
            var darkestColor = ChartGraphics.GetGradientColor(_buttonCurrentColor, SKColors.Black, 0.8);
            var lighterColor = ChartGraphics.GetGradientColor(_buttonCurrentColor, SKColors.White, 0.5);

            // Fill button rectangle background
            graph.FillRectangleRel(
                buttonRect,
                _buttonCurrentColor,
                ChartHatchStyle.None,
                "",
                ChartImageWrapMode.Tile,
                SKColor.Empty,
                ChartImageAlignmentStyle.Center,
                GradientStyle.None,
                SKColor.Empty,
                darkerColor,
                (pressedState) ? 1 : 0,
                ChartDashStyle.Solid,
                SKColor.Empty,
                0,
                PenAlignment.Outset);

            // Check if 2 or 1 pixel border will be drawn (if size too small)
            bool singlePixelBorder = Size <= 12;

            // Draw 3D effect around the button when not pressed
            if (!pressedState)
            {
                // Get relative size of 1 pixel
                SKSize pixelRelativeSize = new(1, 1);
                pixelRelativeSize = graph.GetRelativeSize(pixelRelativeSize);

                // Draw top/left border with button color
                graph.DrawLineRel(
                    (singlePixelBorder) ? lighterColor : _buttonCurrentColor, 1, ChartDashStyle.Solid,
                    new SKPoint(buttonRect.Left, buttonRect.Bottom),
                    new SKPoint(buttonRect.Left, buttonRect.Top));
                graph.DrawLineRel(
                    (singlePixelBorder) ? lighterColor : _buttonCurrentColor, 1, ChartDashStyle.Solid,
                    new SKPoint(buttonRect.Left, buttonRect.Top),
                    new SKPoint(buttonRect.Right, buttonRect.Top));

                // Draw right/bottom border with the darkest color
                graph.DrawLineRel(
                    (singlePixelBorder) ? darkerColor : darkestColor, 1, ChartDashStyle.Solid,
                    new SKPoint(buttonRect.Right, buttonRect.Bottom),
                    new SKPoint(buttonRect.Right, buttonRect.Top));
                graph.DrawLineRel(
                    (singlePixelBorder) ? darkerColor : darkestColor, 1, ChartDashStyle.Solid,
                    new SKPoint(buttonRect.Left, buttonRect.Bottom),
                    new SKPoint(buttonRect.Right, buttonRect.Bottom));

                if (!singlePixelBorder)
                {
                    // Draw right/bottom border (offset 1) with the dark color
                    graph.DrawLineRel(
                        darkerColor, 1, ChartDashStyle.Solid,
                        new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height),
                        new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Top + pixelRelativeSize.Height));
                    graph.DrawLineRel(
                        darkerColor, 1, ChartDashStyle.Solid,
                        new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height),
                        new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height));

                    // Draw top/left border (offset 1) with lighter color
                    graph.DrawLineRel(
                        lighterColor, 1, ChartDashStyle.Solid,
                        new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height),
                        new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Top + pixelRelativeSize.Height));
                    graph.DrawLineRel(
                        lighterColor, 1, ChartDashStyle.Solid,
                        new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Left + pixelRelativeSize.Height),
                        new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Left + pixelRelativeSize.Height));
                }
            }

            // Check axis orientation
            bool verticalAxis = (axis.AxisPosition == AxisPosition.Left ||
                                 axis.AxisPosition == AxisPosition.Right);

            // Set graphics transformation for button pressed mode
            float pressedShifting = (singlePixelBorder) ? 0.5f : 1f;

            if (pressedState)
            {
                graph.TranslateTransform(pressedShifting, pressedShifting);
            }

            // Draw button image
            SKRect buttonAbsRect = graph.GetAbsoluteRectangle(buttonRect);
            float  imageOffset   = (singlePixelBorder) ? 2 : 3;

            switch (buttonType)
            {
            case (ScrollBarButtonType.SmallDecrement):
            {
                // Calculate triangal points position
                SKPoint[] points = new SKPoint[3];
                if (verticalAxis)
                {
                    points[0].X = buttonAbsRect.Left + imageOffset;
                    points[0].Y = buttonAbsRect.Top + (imageOffset + 1f);
                    points[1].X = buttonAbsRect.Left + buttonAbsRect.Width / 2f;
                    points[1].Y = buttonAbsRect.Bottom - imageOffset;
                    points[2].X = buttonAbsRect.Right - imageOffset;
                    points[2].Y = buttonAbsRect.Top + (imageOffset + 1f);
                }
                else
                {
                    points[0].X = buttonAbsRect.Left + imageOffset;
                    points[0].Y = buttonAbsRect.Top + buttonAbsRect.Height / 2f;
                    points[1].X = buttonAbsRect.Right - (imageOffset + 1f);
                    points[1].Y = buttonAbsRect.Top + imageOffset;
                    points[2].X = buttonAbsRect.Right - (imageOffset + 1f);
                    points[2].Y = buttonAbsRect.Bottom - imageOffset;
                }

                using var brush = new SKPaint { Style = SKPaintStyle.Fill, Color = _lineCurrentColor };

                graph.FillPolygon(brush, points);

                break;
            }

            case (ScrollBarButtonType.SmallIncrement):
            {
                // Calculate triangal points position
                SKPoint[] points = new SKPoint[3];
                if (verticalAxis)
                {
                    points[0].X = buttonAbsRect.Left + imageOffset;
                    points[0].Y = buttonAbsRect.Bottom - (imageOffset + 1f);
                    points[1].X = buttonAbsRect.Left + buttonAbsRect.Width / 2f;
                    points[1].Y = buttonAbsRect.Top + imageOffset;
                    points[2].X = buttonAbsRect.Right - imageOffset;
                    points[2].Y = buttonAbsRect.Bottom - (imageOffset + 1f);
                }
                else
                {
                    points[0].X = buttonAbsRect.Right - imageOffset;
                    points[0].Y = buttonAbsRect.Top + buttonAbsRect.Height / 2f;
                    points[1].X = buttonAbsRect.Left + (imageOffset + 1f);
                    points[1].Y = buttonAbsRect.Top + imageOffset;
                    points[2].X = buttonAbsRect.Left + (imageOffset + 1f);
                    points[2].Y = buttonAbsRect.Bottom - imageOffset;
                }

                using var brush = new SKPaint { Style = SKPaintStyle.Fill, Color = _lineCurrentColor };
                graph.FillPolygon(brush, points);

                break;
            }

            case (ScrollBarButtonType.ZoomReset):
            {
                // Draw circule with a minus sign

                using var pen = new SKPaint { Style = SKPaintStyle.Fill, Color = _lineCurrentColor };

                graph.DrawEllipse(pen, buttonAbsRect.Left + imageOffset - 0.5f, buttonAbsRect.Top + imageOffset - 0.5f, buttonAbsRect.Width - 2f * imageOffset, buttonAbsRect.Height - 2f * imageOffset);
                graph.DrawLine(pen, buttonAbsRect.Left + imageOffset + 1.5f, buttonAbsRect.Top + buttonAbsRect.Height / 2f - 0.5f, buttonAbsRect.Right - imageOffset - 2.5f, buttonAbsRect.Top + buttonAbsRect.Height / 2f - 0.5f);

                break;
            }
            }

            // Reset graphics transformation for button pressed mode
            if (pressedState)
            {
                graph.TranslateTransform(-pressedShifting, -pressedShifting);
            }
        }