Exemplo n.º 1
0
        /// <summary>
        /// Draws the line using the MaxPolylinesPerLine and MinPointsPerPolyline properties.
        /// </summary>
        /// <param name="points">The points.</param>
        /// <param name="strokeColor">The stroke color.</param>
        /// <param name="thickness">The thickness.</param>
        /// <param name="lineJoin">The line join.</param>
        /// <param name="dashArray">The dash array. Use <c>null</c> to get a solid line.</param>
        /// <param name="aliased"></param>
        /// <param name="isHitTestVisible"><c>true</c> if hit testing should be enabled, <c>false</c> otherwise.</param>
        /// <remarks>See <a href="https://oxyplot.codeplex.com/discussions/456679">discussion</a>.</remarks>
        private void DrawPolylineBalanced([NotNull] IList <Point> points, Color strokeColor, double thickness, PenLineJoin lineJoin, ICollection <double> dashArray, bool aliased, bool isHitTestVisible)
        {
            // balance the number of points per polyline and the number of polylines
            var numPointsPerPolyline = Math.Max(points.Count / MaxPolylinesPerLine, MinPointsPerPolyline);

            var polyline = Create <Polyline>(isHitTestVisible);

            SetStroke(polyline, strokeColor, thickness, lineJoin, dashArray, 0, aliased);
            var pointCollection = new PointCollection(numPointsPerPolyline);

            var    pointCount        = points.Count;
            double lineLength        = 0;
            var    dashPatternLength = dashArray?.Sum() ?? 0;
            var    last = new Point();

            for (var i = 0; i < pointCount; i++)
            {
                var current = aliased ? ToPixelAlignedPoint(points[i]) : points[i];
                pointCollection.Add(current);

                // get line length
                if (dashArray != null)
                {
                    if (i > 0)
                    {
                        var delta = current - last;
                        var dist  = Math.Sqrt((delta.X * delta.X) + (delta.Y * delta.Y));
                        lineLength += dist;
                    }

                    last = current;
                }

                // use multiple polylines with limited number of points to improve WPF performance
                if (pointCollection.Count >= numPointsPerPolyline)
                {
                    polyline.Points = pointCollection;

                    if (i < pointCount - 1)
                    {
                        // start a new polyline at last point so there is no gap (it is not necessary to use the % operator)
                        var dashOffset = dashPatternLength > 0 ? lineLength / thickness : 0;
                        polyline = Create <Polyline>(isHitTestVisible);
                        SetStroke(polyline, strokeColor, thickness, lineJoin, dashArray, dashOffset, aliased);
                        pointCollection = new PointCollection(numPointsPerPolyline)
                        {
                            pointCollection.Last()
                        };
                    }
                }
            }

            if (pointCollection.Count > 1 || pointCount == 1)
            {
                polyline.Points = pointCollection;
            }
        }
Exemplo n.º 2
0
        /// <inheritdoc/>
        public void DrawPolygon(IList <Point> points, Color fillColor, Color strokeColor,
                                double thickness, PenLineJoin lineJoin, ICollection <double> dashArray, double dashOffset, bool aliased, bool isHitTestVisible)
        {
            var polygon = Create <Polygon>(isHitTestVisible);

            polygon.Fill = GetBrush(fillColor);
            SetStroke(polygon, strokeColor, thickness, lineJoin, dashArray, dashOffset, false);

            polygon.Points = ToPointCollection(points, aliased);
        }
Exemplo n.º 3
0
        /// <inheritdoc/>
        public void DrawLine(Point p1, Point p2, Color strokeColor,
                             double thickness, PenLineJoin lineJoin, ICollection <double> dashArray, double dashOffset, bool aliased, bool isHitTestVisible)
        {
            var line = Create <Line>(isHitTestVisible);

            SetStroke(line, strokeColor, thickness, lineJoin, dashArray, dashOffset, aliased);
            line.X1 = p1.X;
            line.Y1 = p1.Y;
            line.X2 = p2.X;
            line.Y2 = p2.Y;
        }
Exemplo n.º 4
0
        /// <inheritdoc/>
        public void DrawRectangle(Rect rect, Color fillColor, Color strokeColor,
                                  double thickness, PenLineJoin lineJoin, ICollection <double> dashArray, double dashOffset, bool isHitTestVisible)
        {
            var rectangle = Create <Rectangle>(isHitTestVisible, rect.Left, rect.Top);

            rectangle.Fill = GetBrush(fillColor);
            SetStroke(rectangle, strokeColor, thickness, lineJoin, dashArray, dashOffset, false);

            rectangle.Height = rect.Height;
            rectangle.Width  = rect.Width;
            Canvas.SetLeft(rectangle, rect.Left);
            Canvas.SetTop(rectangle, rect.Top);
        }
Exemplo n.º 5
0
        /// <inheritdoc/>
        public void DrawPolyline(IList <Point> points, Color strokeColor,
                                 double thickness, PenLineJoin lineJoin, ICollection <double> dashArray, double dashOffset, bool aliased, bool isHitTestVisible)
        {
            if (thickness < BalancedLineDrawingThicknessLimit)
            {
                DrawPolylineBalanced(points, strokeColor, thickness, lineJoin, dashArray, aliased, isHitTestVisible);
            }

            var polyline = Create <Polyline>(isHitTestVisible);

            SetStroke(polyline, strokeColor, thickness, lineJoin, dashArray, dashOffset, aliased);
            polyline.Points = ToPointCollection(points, aliased);
        }
Exemplo n.º 6
0
        /// <inheritdoc/>
        public void DrawEllipse(Point point, Size size, Color fillColor, Color strokeColor,
                                double thickness, PenLineJoin lineJoin, ICollection <double> dashArray, double dashOffset, bool isHitTestVisible)
        {
            point.Offset(-size.Width / 2, -size.Height / 2);
            var rect = new Rect(point, size);

            var ellipse = Create <Ellipse>(isHitTestVisible, rect.Left, rect.Top);

            ellipse.Fill = GetBrush(fillColor);
            SetStroke(ellipse, strokeColor, thickness, lineJoin, dashArray, dashOffset, false);

            ellipse.Height = rect.Height;
            ellipse.Width  = rect.Width;
            Canvas.SetLeft(ellipse, rect.Left);
            Canvas.SetTop(ellipse, rect.Top);
        }
Exemplo n.º 7
0
        private void SetStroke([NotNull] Shape shape, Color color, double thickness, PenLineJoin lineJoin, ICollection <double> dashArray, double dashOffset, bool aliased)
        {
            shape.Stroke          = GetBrush(color);
            shape.StrokeThickness = thickness;
            shape.StrokeLineJoin  = lineJoin;
            if (dashArray != null)
            {
                shape.StrokeDashArray  = new DoubleCollection(dashArray);
                shape.StrokeDashOffset = dashOffset;
            }

            if (aliased)
            {
                shape.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
                shape.SnapsToDevicePixels = true;
            }
        }
Exemplo n.º 8
0
        /// <inheritdoc/>
        public void DrawText(Point point, Color color, string text, FontFamily fontFamily, double fontSize, FontWeight fontWeight,
                             HorizontalAlignment hAlign, VerticalAlignment vAlign, bool isHitTestVisible)
        {
            var textBlock = Create <TextBlock>(isHitTestVisible);

            textBlock.Foreground = GetBrush(color);
            textBlock.FontFamily = fontFamily;
            textBlock.FontSize   = fontSize;
            textBlock.FontWeight = fontWeight;
            textBlock.Text       = text;

            var dx = 0.0;
            var dy = 0.0;

            if (hAlign != HorizontalAlignment.Left || vAlign != VerticalAlignment.Top)
            {
                textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
                var size = textBlock.DesiredSize;
                if (hAlign == HorizontalAlignment.Center)
                {
                    dx = -size.Width / 2;
                }

                if (hAlign == HorizontalAlignment.Right)
                {
                    dx = -size.Width;
                }

                if (vAlign == VerticalAlignment.Center)
                {
                    dy = -size.Height / 2;
                }

                if (vAlign == VerticalAlignment.Bottom)
                {
                    dy = -size.Height;
                }
            }

            textBlock.RenderTransform = new TranslateTransform(point.X + dx, point.Y + dy);
            textBlock.SetValue(RenderOptions.ClearTypeHintProperty, ClearTypeHint.Enabled);
        }
Exemplo n.º 9
0
        /// <inheritdoc/>
        public void DrawLineSegments(IList <Point> points, Color strokeColor,
                                     double thickness, PenLineJoin lineJoin, ICollection <double> dashArray, double dashOffset, bool aliased, bool isHitTestVisible)
        {
            if (points == null)
            {
                throw new ArgumentNullException(nameof(points));
            }
            if (points.Count < 2)
            {
                return;
            }

            if (UseStreamGeometry)
            {
                DrawLineSegmentsByStreamGeometry(points, strokeColor, thickness, lineJoin, dashArray, dashOffset, aliased, isHitTestVisible);
                return;
            }

            var pathGeometry = new PathGeometry();

            for (var i = 0; i < points.Count - 1; i += 2)
            {
                var figure = new PathFigure
                {
                    IsClosed   = false,
                    StartPoint = aliased ? ToPixelAlignedPoint(points[i]) : points[i],
                };
                var segment = new LineSegment
                {
                    IsSmoothJoin = false,
                    IsStroked    = true,
                    Point        = aliased ? ToPixelAlignedPoint(points[i + 1]) : points[i + 1],
                };
                figure.Segments.Add(segment);
                pathGeometry.Figures.Add(figure);
            }

            var path = Create <Path>(isHitTestVisible);

            SetStroke(path, strokeColor, thickness, lineJoin, dashArray, dashOffset, aliased);
            path.Data = pathGeometry;
        }
Exemplo n.º 10
0
        /// <summary>
        /// Gets a brush for the given <paramref name="color"/>.
        /// </summary>
        /// <remarks>Brushes are cached and frozen to improve performance.</remarks>
        /// <seealso cref="Freezable.Freeze"/>
        /// <param name="color"></param>
        /// <returns></returns>
        private Brush GetBrush(Color color)
        {
            if (color.A == 0)
            {
                // If color is fully transparent, no need for a brush
                return(null);
            }

            Brush brush;

            if (!cachedBrushes.TryGetValue(color, out brush))
            {
                brush = new SolidColorBrush(color.ToSystemColor());
                if (brush.CanFreeze)
                {
                    brush.Freeze(); // Freezing should improve rendering performance
                }
                cachedBrushes.Add(color, brush);
            }

            return(brush);
        }
Exemplo n.º 11
0
        /// <inheritdoc/>
        public void DrawEllipses(IList <Point> points, double radiusX, double radiusY, Color fillColor, Color strokeColor,
                                 double thickness, PenLineJoin lineJoin, ICollection <double> dashArray, double dashOffset, bool isHitTestVisible)
        {
            if (points == null)
            {
                throw new ArgumentNullException(nameof(points));
            }
            if (points.Count == 0)
            {
                return;
            }

            var fillBrush   = GetBrush(fillColor);
            var strokeBrush = GetBrush(strokeColor);
            var pen         = new Pen(strokeBrush, thickness)
            {
                LineJoin  = lineJoin,
                DashStyle = new DashStyle(dashArray, dashOffset),
            };

            var visual  = new DrawingVisual();
            var context = visual.RenderOpen();

            foreach (var point in points)
            {
                context.DrawEllipse(fillBrush, pen, point, radiusX, radiusY);
            }
            context.Close();

            var host = Create <VisualHost>(isHitTestVisible);

            host.AddChild(visual);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Draws the line segments by stream geometry.
        /// </summary>
        /// <param name="points">The points.</param>
        /// <param name="strokeColor">The stroke color.</param>
        /// <param name="thickness">The thickness.</param>
        /// <param name="lineJoin">The line join.</param>
        /// <param name="dashArray">The dash array. Use <c>null</c> to get a solid line.</param>
        /// <param name="dashOffset">The distance within the dash pattern where a dash begins.</param>
        /// <param name="aliased"></param>
        /// <param name="isHitTestVisible"><c>true</c> if hit testing should be enabled, <c>false</c> otherwise.</param>
        /// <remarks>Using stream geometry seems to be slightly faster than using path geometry.</remarks>
        private void DrawLineSegmentsByStreamGeometry([NotNull] IList <Point> points, Color strokeColor,
                                                      double thickness, PenLineJoin lineJoin, ICollection <double> dashArray, double dashOffset, bool aliased, bool isHitTestVisible)
        {
            var streamGeometry = new StreamGeometry();

            var streamGeometryContext = streamGeometry.Open();

            for (var i = 0; i < points.Count - 1; i += 2)
            {
                streamGeometryContext.BeginFigure(aliased ? ToPixelAlignedPoint(points[i]) : points[i], false, false);
                streamGeometryContext.LineTo(aliased ? ToPixelAlignedPoint(points[i + 1]) : points[i + 1], true, false);
            }
            streamGeometryContext.Close();

            var path = Create <Path>(isHitTestVisible);

            SetStroke(path, strokeColor, thickness, lineJoin, dashArray, dashOffset, aliased);
            path.Data = streamGeometry;
        }
Exemplo n.º 13
0
        /// <inheritdoc/>
        public void DrawTexts(IList <Point> points, Color color, IList <string> texts, FontFamily fontFamily, double fontSize, FontWeight fontWeight,
                              HorizontalAlignment hAlign, VerticalAlignment vAlign, bool isHitTestVisible)
        {
            if (points == null)
            {
                throw new ArgumentNullException(nameof(points));
            }
            if (texts == null)
            {
                throw new ArgumentNullException(nameof(texts));
            }

            if (points.Count != texts.Count)
            {
                throw new ArgumentException($"{nameof(points)} and {nameof(texts)} must have the same number of elements.");
            }

            var brush    = GetBrush(color);
            var typeFace = new Typeface(fontFamily, FontStyles.Normal, fontWeight, FontStretches.Normal);

            var visual  = new DrawingVisual();
            var context = visual.RenderOpen();

            for (var i = 0; i < points.Count; ++i)
            {
                var text      = texts[i];
                var point     = points[i];
                var formatted = new FormattedText(text, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, typeFace, fontSize, brush);
                var dx        = 0.0;
                var dy        = 0.0;
                if (hAlign != HorizontalAlignment.Left || vAlign != VerticalAlignment.Top)
                {
                    var size = new Size(formatted.Width, formatted.Height);
                    if (hAlign == HorizontalAlignment.Center)
                    {
                        dx = -size.Width / 2;
                    }

                    if (hAlign == HorizontalAlignment.Right)
                    {
                        dx = -size.Width;
                    }

                    if (vAlign == VerticalAlignment.Center)
                    {
                        dy = -size.Height / 2;
                    }

                    if (vAlign == VerticalAlignment.Bottom)
                    {
                        dy = -size.Height;
                    }
                }
                point.Offset(dx, dy);
                context.DrawText(formatted, point);
            }
            context.Close();

            var host = Create <VisualHost>(isHitTestVisible);

            host.AddChild(visual);
        }