Example #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));
                            }
                        }
                    }
                }
            }
        }
Example #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;

#if !SILVERLIGHT
            // 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;
#endif

            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 !SILVERLIGHT
                        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;
                                }
                            }
                        }
#endif

                        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();
        }