diff --git a/MapControl/Avalonia/MapPolypoint.Avalonia.cs b/MapControl/Avalonia/MapPolypoint.Avalonia.cs index 48be8a38..4875cd9d 100644 --- a/MapControl/Avalonia/MapPolypoint.Avalonia.cs +++ b/MapControl/Avalonia/MapPolypoint.Avalonia.cs @@ -51,31 +51,39 @@ namespace MapControl protected void UpdateData(IEnumerable locations, bool closed) { - var pathFigure = new PathFigure(); + var pathFigures = new PathFigures(); - if (ParentMap != null && locations?.Count() >= 2) + if (ParentMap != null && locations != null) { - var longitudeOffset = GetLongitudeOffset(Location ?? locations.First()); + var longitudeOffset = GetLongitudeOffset(Location ?? locations.FirstOrDefault()); - AddPolylinePoints(pathFigure, locations, longitudeOffset, closed); + AddPolylinePoints(pathFigures, locations, longitudeOffset, closed); } - ((PathGeometry)Data).Figures = new PathFigures { pathFigure }; + ((PathGeometry)Data).Figures = pathFigures; - InvalidateGeometry(); // ignores an empty PathGeometry.Figures collection + InvalidateGeometry(); } - private void AddPolylinePoints(PathFigure pathFigure, IEnumerable locations, double longitudeOffset, bool closed) + private void AddPolylinePoints(PathFigures pathFigures, IEnumerable locations, double longitudeOffset, bool closed) { var points = locations .Select(location => LocationToView(location, longitudeOffset)) .Where(point => point.HasValue) .Select(point => point.Value); - pathFigure.StartPoint = points.First(); - pathFigure.Segments.Add(new PolyLineSegment(points.Skip(1))); - pathFigure.IsClosed = closed; - pathFigure.IsFilled = true; + if (points.Any()) + { + var figure = new PathFigure + { + StartPoint = points.First(), + IsClosed = closed, + IsFilled = true + }; + + figure.Segments.Add(new PolyLineSegment(points.Skip(1))); + pathFigures.Add(figure); + } } } } diff --git a/MapControl/WPF/MapPolypoint.WPF.cs b/MapControl/WPF/MapPolypoint.WPF.cs index 56963393..f71c5bab 100644 --- a/MapControl/WPF/MapPolypoint.WPF.cs +++ b/MapControl/WPF/MapPolypoint.WPF.cs @@ -60,9 +60,9 @@ namespace MapControl { using (var context = ((StreamGeometry)Data).Open()) { - if (ParentMap != null && locations?.Count() >= 2) + if (ParentMap != null && locations != null) { - var longitudeOffset = GetLongitudeOffset(Location ?? locations.First()); + var longitudeOffset = GetLongitudeOffset(Location ?? locations.FirstOrDefault()); AddPolylinePoints(context, locations, longitudeOffset, closed); } @@ -77,7 +77,7 @@ namespace MapControl { var longitudeOffset = GetLongitudeOffset(Location); - foreach (var polygon in polygons.Where(p => p?.Count() >= 2)) + foreach (var polygon in polygons) { AddPolylinePoints(context, polygon, longitudeOffset, true); } @@ -92,8 +92,11 @@ namespace MapControl .Where(point => point.HasValue) .Select(point => point.Value); - context.BeginFigure(points.First(), true, closed); - context.PolyLineTo(points.Skip(1).ToList(), true, true); + if (points.Any()) + { + context.BeginFigure(points.First(), true, closed); + context.PolyLineTo(points.Skip(1).ToList(), true, true); + } } } } diff --git a/MapControl/WinUI/MapPolypoint.WinUI.cs b/MapControl/WinUI/MapPolypoint.WinUI.cs index e62974cf..f2891d3e 100644 --- a/MapControl/WinUI/MapPolypoint.WinUI.cs +++ b/MapControl/WinUI/MapPolypoint.WinUI.cs @@ -2,7 +2,6 @@ // Copyright © 2024 Clemens Fischer // Licensed under the Microsoft Public License (Ms-PL) -using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; @@ -62,9 +61,9 @@ namespace MapControl var pathFigures = ((PathGeometry)Data).Figures; pathFigures.Clear(); - if (ParentMap != null && locations?.Count() >= 2) + if (ParentMap != null && locations != null) { - var longitudeOffset = GetLongitudeOffset(Location ?? locations.First()); + var longitudeOffset = GetLongitudeOffset(Location ?? locations.FirstOrDefault()); AddPolylinePoints(pathFigures, locations, longitudeOffset, closed); } @@ -77,12 +76,12 @@ namespace MapControl .Where(point => point.HasValue) .Select(point => point.Value); - if (closed) + if (points.Any()) { var figure = new PathFigure { StartPoint = points.First(), - IsClosed = true, + IsClosed = closed, IsFilled = true }; @@ -96,133 +95,6 @@ namespace MapControl figure.Segments.Add(polyline); pathFigures.Add(figure); } - else - { - PathFigure figure = null; - PolyLineSegment polyline = null; - var viewport = new Rect(0, 0, ParentMap.RenderSize.Width, ParentMap.RenderSize.Height); - var pointList = points.ToList(); - - for (int i = 1; i < pointList.Count; i++) - { - var p1 = pointList[i - 1]; - var p2 = pointList[i]; - var inside = GetIntersections(ref p1, ref p2, viewport); - - if (inside) - { - if (figure == null) - { - figure = new PathFigure - { - StartPoint = p1, - IsClosed = false, - IsFilled = true - }; - - polyline = new PolyLineSegment(); - figure.Segments.Add(polyline); - pathFigures.Add(figure); - } - - polyline.Points.Add(p2); - } - - if (!inside || p2 != pointList[i]) - { - figure = null; - } - } - } - } - - /// - /// Calculates the potential intersections of a line segment given by (p1,p2) with a rectangle. - /// Updates either p1, p2, or both with any found intersection and returns a value that indicates - /// whether the segment intersects or lies inside the rectangle. - /// - private static bool GetIntersections(ref Point p1, ref Point p2, Rect rect) - { - if (rect.Contains(p1) && rect.Contains(p2)) - { - return true; - } - - var topLeft = new Point(rect.X, rect.Y); - var topRight = new Point(rect.X + rect.Width, rect.Y); - var bottomLeft = new Point(rect.X, rect.Y + rect.Height); - var bottomRight = new Point(rect.X + rect.Width, rect.Y + rect.Height); - var numIntersections = 0; - - if (GetIntersection(ref p1, ref p2, topLeft, bottomLeft, p => p.X <= rect.X)) // left edge - { - numIntersections++; - } - - if (GetIntersection(ref p1, ref p2, topLeft, topRight, p => p.Y <= rect.Y)) // top edge - { - numIntersections++; - } - - if (numIntersections < 2 && - GetIntersection(ref p1, ref p2, topRight, bottomRight, p => p.X >= rect.X + rect.Width)) // right edge - { - numIntersections++; - } - - if (numIntersections < 2 && - GetIntersection(ref p1, ref p2, bottomLeft, bottomRight, p => p.Y >= rect.Y + rect.Height)) // bottom edge - { - numIntersections++; - } - - return numIntersections > 0; - } - - private static bool GetIntersection(ref Point p1, ref Point p2, Point p3, Point p4, Predicate predicate) - { - var intersection = GetIntersection(p1, p2, p3, p4); - - if (!intersection.HasValue) - { - return false; - } - - if (predicate(p1)) - { - p1 = intersection.Value; - } - else - { - p2 = intersection.Value; - } - - return true; - } - - /// - /// Returns the intersection point of two line segments given by (p1,p2) and (p3,p4), - /// or null if no intersection exists. See https://stackoverflow.com/a/1968345. - /// - private static Point? GetIntersection(Point p1, Point p2, Point p3, Point p4) - { - var x12 = p2.X - p1.X; - var y12 = p2.Y - p1.Y; - var x34 = p4.X - p3.X; - var y34 = p4.Y - p3.Y; - var x13 = p3.X - p1.X; - var y13 = p3.Y - p1.Y; - - var d = x12 * y34 - x34 * y12; - var s = (x13 * y12 - y13 * x12) / d; - var t = (x13 * y34 - y13 * x34) / d; - - if (s >= 0d && s <= 1d && t >= 0d && t <= 1d) - { - return new Point(p1.X + t * x12, p1.Y + t * y12); - } - - return null; } } }