Пример #1
0
        private void UpdateMinorGridLines()
        {
            Axis xAxis = XAxis;
            Axis yAxis = YAxis;
            if (xAxis != null && yAxis != null)
            {
                AxisScale xScale = xAxis.Scale;
                AxisScale yScale = yAxis.Scale;
                if (xScale != null && yScale != null)
                {
                    double xMin = xAxis.GetPosition(xScale.Min);
                    double xMax = xAxis.GetPosition(xScale.Max);
                    double yMin = yAxis.GetPosition(yScale.Min);
                    double yMax = yAxis.GetPosition(yScale.Max);

                    // Add vertical minor lines
                    if (_verticalMinorLinesRenderer != null && VerticalMinorLineStyle != null)
                    {
                        using (var renderContext = _verticalMinorLinesRenderer.Open())
                        {
                            for (int i = 0; i < xAxis.MinorTicks.Length; ++i)
                            {
                                double x = xAxis.GetPosition(xAxis.MinorTicks[i]);
                                renderContext.DrawLine(new Point(x, yMin), new Point(x, yMax));
                            }
                        }
                    }

                    // Add horizontal minor lines
                    if (_horizontalMinorLinesRenderer != null && HorizontalMinorLineStyle != null)
                    {
                        using (var renderContext = _horizontalMinorLinesRenderer.Open())
                        {
                            for (int i = 0; i < yAxis.MinorTicks.Length; ++i)
                            {
                                double y = yAxis.GetPosition(yAxis.MinorTicks[i]);
                                renderContext.DrawLine(new Point(xMin, y), new Point(xMax, y));
                            }
                        }
                    }
                }
            }
        }
Пример #2
0
        protected virtual void OnUpdateLines(int startIndex, int endIndexExclusive, double[] xPositions, double[] basePositions, double[] yPositions)
        {
            if (Data.Count == 0)
                return;

            bool reversed = XAxis.Scale.Reversed;
            bool horizontalStepLineVisible = HorizontalStepLineVisible;
            bool verticalStepLineVisible = VerticalStepLineVisible;
            bool filled = Filled;
            var interpolation = EffectiveInterpolation;


            // Perform the large data optimization (see below) if the line chart contains vertical lines.
            bool largeDataOptimization = interpolation == ChartInterpolation.Linear
                                         || interpolation == ChartInterpolation.CenteredSteps && verticalStepLineVisible
                                         || interpolation == ChartInterpolation.LeftSteps && verticalStepLineVisible
                                         || interpolation == ChartInterpolation.RightSteps && verticalStepLineVisible;
            double pixelSize = WindowsHelper.GetPixelSize(this).Width;


            using (var lineRenderContext = _lineRenderer.Open())
            using (var areaRenderContext = _areaRenderer.Open())
            {
                int numberOfDataPoints = Data.Count;

                // Lines are drawn from index i to i+1.
                startIndex = Math.Max(0, startIndex - 1);

                // For centered steps one additional data point needs to be rendered.
                if (interpolation == ChartInterpolation.CenteredSteps)
                    endIndexExclusive = Math.Min(numberOfDataPoints, endIndexExclusive + 1);

                for (int i = startIndex; i < endIndexExclusive; i++)
                {
                    if (Numeric.IsNaN(xPositions[i]) || Numeric.IsNaN(yPositions[i]))
                        continue;


                    if (largeDataOptimization)
                    {
                        // Draw a single vertical line for all data points that lie on the same pixel column.
                        double xPixel = WindowsHelper.RoundToDevicePixelsCenter(xPositions[i], pixelSize);
                        double yMin = yPositions[i];
                        double yMax = yPositions[i];
                        int overlap = 0;

                        for (int j = i + 1; j < endIndexExclusive; j++)
                        {
                            // ReSharper disable once CompareOfFloatsByEqualityOperator
                            if (Numeric.IsNaN(xPositions[j])
                                || Numeric.IsNaN(yPositions[j])
                                || xPixel != WindowsHelper.RoundToDevicePixelsCenter(xPositions[j], pixelSize))
                            {
                                break;
                            }

                            overlap++;
                            if (yPositions[j] < yMin)          // Safe for NaN.
                                yMin = yPositions[j];
                            else if (yPositions[j] > yMax)     // Safe for NaN.
                                yMax = yPositions[j];
                        }

                        if (overlap > 1)
                        {
                            lineRenderContext.DrawLine(new Point(xPixel, yMin), new Point(xPixel, yMax));

                            // i ............. index of first point in overlap.
                            // i + overlap ... index of last point in overlap.

                            if (filled && !Numeric.IsNaN(basePositions[i]) && !Numeric.IsNaN(basePositions[i + overlap]))
                                areaRenderContext.DrawPolygon(
                                    new Point(xPositions[i], yMin),
                                    new Point(xPositions[i + overlap], yMin),
                                    new Point(xPositions[i + overlap], basePositions[i + overlap]),
                                    new Point(xPositions[i], basePositions[i]));

                            // Jump ahead to last point in overlap.
                            i += overlap;

                            if (Numeric.IsNaN(yPositions[i]))
                                continue;
                        }
                    }


                    Point previousPoint; //, previousPointBase;
                    Point point, pointBase;
                    Point nextPoint, nextPointBase;

                    if (i - 1 >= 0)
                    {
                        previousPoint = new Point(xPositions[i - 1], yPositions[i - 1]);
                        //previousPointBase = new Point(xPositions[i - 1], basePositions[i - 1]);
                    }
                    else
                    {
                        previousPoint = new Point(double.NaN, double.NaN);
                        //previousPointBase = new Point(double.NaN, double.NaN);
                    }

                    point = new Point(xPositions[i], yPositions[i]);
                    pointBase = new Point(xPositions[i], basePositions[i]);

                    if (i + 1 < numberOfDataPoints)
                    {
                        nextPoint = new Point(xPositions[i + 1], yPositions[i + 1]);
                        nextPointBase = new Point(xPositions[i + 1], basePositions[i + 1]);
                    }
                    else
                    {
                        nextPoint = new Point(double.NaN, double.NaN);
                        nextPointBase = new Point(double.NaN, double.NaN);
                    }

                    // Draw lines and area from i to i+1.
                    if (interpolation == ChartInterpolation.Linear)
                    {
                        // Linear interpolation
                        if (!Numeric.IsNaN(nextPoint.X) && !Numeric.IsNaN(nextPoint.Y))
                        {
                            lineRenderContext.DrawLine(point, nextPoint);

                            if (filled && !Numeric.IsNaN(pointBase.Y) && !Numeric.IsNaN(nextPointBase.Y))
                                areaRenderContext.DrawPolygon(
                                    point,
                                    nextPoint,
                                    nextPointBase,
                                    pointBase);
                        }
                    }
                    else
                    {
                        if (interpolation == ChartInterpolation.CenteredSteps)
                        {
                            // Centered steps
                            double centerBefore, centerAfter;
                            GetCenteredStep(previousPoint, point, nextPoint, out centerBefore, out centerAfter);

                            if (horizontalStepLineVisible)
                                lineRenderContext.DrawLine(new Point(centerBefore, point.Y), new Point(centerAfter, point.Y));

                            if (verticalStepLineVisible && !Numeric.IsNaN(nextPoint.X) && !Numeric.IsNaN(nextPoint.Y))
                                lineRenderContext.DrawLine(new Point(centerAfter, point.Y), new Point(centerAfter, nextPoint.Y));

                            if (filled && !Numeric.IsNaN(pointBase.Y))
                            {
                                areaRenderContext.DrawPolygon(
                                    new Point(centerBefore, point.Y),
                                    new Point(centerAfter, point.Y),
                                    new Point(centerAfter, pointBase.Y),
                                    new Point(centerBefore, pointBase.Y));
                            }
                        }
                        else
                        {
                            if (interpolation == ChartInterpolation.LeftSteps && !reversed
                                || interpolation == ChartInterpolation.RightSteps && reversed)
                            {
                                // LeftSteps or Reversed RightSteps
                                if (!Numeric.IsNaN(nextPoint.X) && !Numeric.IsNaN(nextPoint.Y))
                                {
                                    if (verticalStepLineVisible)
                                        lineRenderContext.DrawLine(point, new Point(point.X, nextPoint.Y));

                                    if (horizontalStepLineVisible)
                                        lineRenderContext.DrawLine(new Point(point.X, nextPoint.Y), nextPoint);

                                    if (filled && !Numeric.IsNaN(nextPointBase.Y))
                                    {
                                        areaRenderContext.DrawPolygon(
                                            new Point(point.X, nextPoint.Y),
                                            nextPoint,
                                            nextPointBase,
                                            new Point(point.X, nextPointBase.Y));
                                    }
                                }
                            }
                            else
                            {
                                // RightSteps or Reversed LeftSteps
                                if (!Numeric.IsNaN(nextPoint.X) && !Numeric.IsNaN(nextPoint.Y))
                                {
                                    if (horizontalStepLineVisible)
                                        lineRenderContext.DrawLine(point, new Point(nextPoint.X, point.Y));

                                    if (verticalStepLineVisible)
                                        lineRenderContext.DrawLine(new Point(nextPoint.X, point.Y), nextPoint);

                                    if (filled && !Numeric.IsNaN(pointBase.Y) && !Numeric.IsNaN(nextPointBase.Y))
                                    {
                                        areaRenderContext.DrawPolygon(
                                            point,
                                            new Point(nextPoint.X, point.Y),
                                            new Point(nextPointBase.X, pointBase.Y),
                                            pointBase);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (_linePath != null)
                _linePath.Clip = LineClipGeometry;

            if (_areaPath != null)
                _areaPath.Clip = AreaClipGeometry;

            // Bugfix:
            // Sometimes the first line of a Path is not drawn.
            // We need to explicitly call InvalidateMeasure() on the canvas.
            Canvas.InvalidateMeasure();
        }