mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2026-01-11 11:10:19 +01:00
Reworked MapGraticule
This commit is contained in:
parent
53a291662d
commit
28f65140c4
|
|
@ -28,10 +28,20 @@ namespace MapControl
|
|||
{
|
||||
private class Label
|
||||
{
|
||||
public string LatitudeText { get; set; }
|
||||
public string LongitudeText { get; set; }
|
||||
public Point Position { get; set; }
|
||||
public double Rotation { get; set; }
|
||||
public Label(string latText, string lonText, double x, double y, double rotation)
|
||||
{
|
||||
LatitudeText = latText;
|
||||
LongitudeText = lonText;
|
||||
X = x;
|
||||
Y = y;
|
||||
Rotation = rotation;
|
||||
}
|
||||
|
||||
public string LatitudeText { get; }
|
||||
public string LongitudeText { get; }
|
||||
public double X { get; }
|
||||
public double Y { get; }
|
||||
public double Rotation { get; }
|
||||
}
|
||||
|
||||
private const double LineInterpolationResolution = 2d;
|
||||
|
|
@ -96,7 +106,7 @@ namespace MapControl
|
|||
labelFormat, hemisphere, seconds / 3600, seconds / 60 % 60, seconds % 60);
|
||||
}
|
||||
|
||||
private void AddLabel(ICollection<Label> labels, Point position, Location location, double? rotation = null)
|
||||
private void AddLabel(ICollection<Label> labels, Location location, Point position, double? rotation = null)
|
||||
{
|
||||
if (MapProjection.IsValid(position) &&
|
||||
position.X >= 0d && position.X <= ParentMap.RenderSize.Width &&
|
||||
|
|
@ -104,8 +114,9 @@ namespace MapControl
|
|||
{
|
||||
if (!rotation.HasValue)
|
||||
{
|
||||
var pos = ParentMap.LocationToView(new Location(
|
||||
location.Latitude, location.Longitude + 10d / PixelPerLongitudeDegree(location)));
|
||||
location.Longitude += 10d / PixelPerLongitudeDegree(location);
|
||||
|
||||
var pos = ParentMap.LocationToView(location);
|
||||
|
||||
if (MapProjection.IsValid(pos))
|
||||
{
|
||||
|
|
@ -115,68 +126,32 @@ namespace MapControl
|
|||
|
||||
if (rotation.HasValue)
|
||||
{
|
||||
labels.Add(new Label
|
||||
{
|
||||
LatitudeText = GetLabelText(location.Latitude, "NS"),
|
||||
LongitudeText = GetLabelText(Location.NormalizeLongitude(location.Longitude), "EW"),
|
||||
Position = position,
|
||||
Rotation = rotation.Value
|
||||
});
|
||||
labels.Add(new Label(
|
||||
GetLabelText(location.Latitude, "NS"),
|
||||
GetLabelText(Location.NormalizeLongitude(location.Longitude), "EW"),
|
||||
position.X, position.Y, rotation.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GetLatitudeRange(double lineDistance, ref double minLatitude, ref double maxLatitude)
|
||||
private ICollection<Label> DrawGraticule(PathFigureCollection figures)
|
||||
{
|
||||
var width = ParentMap.RenderSize.Width;
|
||||
var height = ParentMap.RenderSize.Height;
|
||||
var northPole = ParentMap.LocationToView(new Location(90d, 0d));
|
||||
var southPole = ParentMap.LocationToView(new Location(-90d, 0d));
|
||||
var labels = new List<Label>();
|
||||
|
||||
if (northPole.X >= 0d && northPole.Y >= 0d && northPole.X <= width && northPole.Y <= height)
|
||||
figures.Clear();
|
||||
|
||||
SetLineDistance();
|
||||
|
||||
if (ParentMap.MapProjection.Type <= MapProjectionType.NormalCylindrical)
|
||||
{
|
||||
maxLatitude = 90d;
|
||||
DrawCylindricalGraticule(figures, labels);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawGraticule(figures, labels);
|
||||
}
|
||||
|
||||
if (southPole.X >= 0d && southPole.Y >= 0d && southPole.X <= width && southPole.Y <= height)
|
||||
{
|
||||
minLatitude = -90d;
|
||||
}
|
||||
|
||||
if (minLatitude > -90d || maxLatitude < 90d)
|
||||
{
|
||||
var locations = new Location[]
|
||||
{
|
||||
ParentMap.ViewToLocation(new Point(0d, 0d)),
|
||||
ParentMap.ViewToLocation(new Point(width / 2d, 0d)),
|
||||
ParentMap.ViewToLocation(new Point(width, 0d)),
|
||||
ParentMap.ViewToLocation(new Point(width, height / 2d)),
|
||||
ParentMap.ViewToLocation(new Point(width, height)),
|
||||
ParentMap.ViewToLocation(new Point(width / 2d, height)),
|
||||
ParentMap.ViewToLocation(new Point(0d, height)),
|
||||
ParentMap.ViewToLocation(new Point(0d, height / 2)),
|
||||
};
|
||||
|
||||
var latitudes = locations.Where(loc => loc != null).Select(loc => loc.Latitude);
|
||||
var south = -90d;
|
||||
var north = 90d;
|
||||
|
||||
if (latitudes.Distinct().Count() >= 2)
|
||||
{
|
||||
south = latitudes.Min();
|
||||
north = latitudes.Max();
|
||||
}
|
||||
|
||||
if (minLatitude > -90d)
|
||||
{
|
||||
minLatitude = Math.Max(Math.Floor(south / lineDistance) * lineDistance, -90d);
|
||||
}
|
||||
|
||||
if (maxLatitude < 90d)
|
||||
{
|
||||
maxLatitude = Math.Min(Math.Ceiling(north / lineDistance) * lineDistance, 90d);
|
||||
}
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
|
||||
private void DrawCylindricalGraticule(PathFigureCollection figures, ICollection<Label> labels)
|
||||
|
|
@ -205,16 +180,13 @@ namespace MapControl
|
|||
{
|
||||
figures.Add(CreateLineFigure(p1, p2));
|
||||
}
|
||||
}
|
||||
|
||||
for (var lat = latLabelStart; lat <= bounds.North; lat += lineDistance)
|
||||
{
|
||||
for (var lon = lonLabelStart; lon <= bounds.East; lon += lineDistance)
|
||||
for (var lat = latLabelStart; lat <= bounds.North; lat += lineDistance)
|
||||
{
|
||||
var location = new Location(lat, lon);
|
||||
var position = ParentMap.LocationToView(location);
|
||||
|
||||
AddLabel(labels, position, location, ParentMap.ViewTransform.Rotation);
|
||||
AddLabel(labels, location, position, ParentMap.ViewTransform.Rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -274,7 +246,7 @@ namespace MapControl
|
|||
if (MapProjection.IsValid(position))
|
||||
{
|
||||
points.Add(position);
|
||||
AddLabel(labels, position, location);
|
||||
AddLabel(labels, location, position);
|
||||
}
|
||||
|
||||
for (int j = 0; j < lonSegments; j++)
|
||||
|
|
@ -291,7 +263,7 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
AddLabel(labels, position, location);
|
||||
AddLabel(labels, location, position);
|
||||
}
|
||||
|
||||
if (points.Count >= 2)
|
||||
|
|
@ -329,6 +301,59 @@ namespace MapControl
|
|||
return visible;
|
||||
}
|
||||
|
||||
private void GetLatitudeRange(double lineDistance, ref double minLatitude, ref double maxLatitude)
|
||||
{
|
||||
var width = ParentMap.RenderSize.Width;
|
||||
var height = ParentMap.RenderSize.Height;
|
||||
var northPole = ParentMap.LocationToView(new Location(90d, 0d));
|
||||
var southPole = ParentMap.LocationToView(new Location(-90d, 0d));
|
||||
|
||||
if (northPole.X >= 0d && northPole.Y >= 0d && northPole.X <= width && northPole.Y <= height)
|
||||
{
|
||||
maxLatitude = 90d;
|
||||
}
|
||||
|
||||
if (southPole.X >= 0d && southPole.Y >= 0d && southPole.X <= width && southPole.Y <= height)
|
||||
{
|
||||
minLatitude = -90d;
|
||||
}
|
||||
|
||||
if (minLatitude > -90d || maxLatitude < 90d)
|
||||
{
|
||||
var locations = new Location[]
|
||||
{
|
||||
ParentMap.ViewToLocation(new Point(0d, 0d)),
|
||||
ParentMap.ViewToLocation(new Point(width / 2d, 0d)),
|
||||
ParentMap.ViewToLocation(new Point(width, 0d)),
|
||||
ParentMap.ViewToLocation(new Point(width, height / 2d)),
|
||||
ParentMap.ViewToLocation(new Point(width, height)),
|
||||
ParentMap.ViewToLocation(new Point(width / 2d, height)),
|
||||
ParentMap.ViewToLocation(new Point(0d, height)),
|
||||
ParentMap.ViewToLocation(new Point(0d, height / 2)),
|
||||
};
|
||||
|
||||
var latitudes = locations.Where(loc => loc != null).Select(loc => loc.Latitude);
|
||||
var south = -90d;
|
||||
var north = 90d;
|
||||
|
||||
if (latitudes.Distinct().Count() >= 2)
|
||||
{
|
||||
south = latitudes.Min();
|
||||
north = latitudes.Max();
|
||||
}
|
||||
|
||||
if (minLatitude > -90d)
|
||||
{
|
||||
minLatitude = Math.Max(Math.Floor(south / lineDistance) * lineDistance, -90d);
|
||||
}
|
||||
|
||||
if (maxLatitude < 90d)
|
||||
{
|
||||
maxLatitude = Math.Min(Math.Ceiling(north / lineDistance) * lineDistance, 90d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PathFigure CreateLineFigure(Point p1, Point p2)
|
||||
{
|
||||
var figure = new PathFigure
|
||||
|
|
|
|||
|
|
@ -26,49 +26,41 @@ namespace MapControl
|
|||
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
{
|
||||
var projection = ParentMap?.MapProjection;
|
||||
|
||||
if (projection != null)
|
||||
if (ParentMap != null)
|
||||
{
|
||||
var typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
|
||||
var pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip;
|
||||
var pathGeometry = new PathGeometry();
|
||||
var labels = new List<Label>();
|
||||
|
||||
SetLineDistance();
|
||||
|
||||
if (projection.Type <= MapProjectionType.NormalCylindrical)
|
||||
{
|
||||
DrawCylindricalGraticule(pathGeometry.Figures, labels);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawGraticule(pathGeometry.Figures, labels);
|
||||
}
|
||||
var labels = DrawGraticule(pathGeometry.Figures);
|
||||
|
||||
drawingContext.DrawGeometry(null, CreatePen(), pathGeometry);
|
||||
|
||||
foreach (var label in labels)
|
||||
if (labels.Count > 0)
|
||||
{
|
||||
var latText = new FormattedText(label.LatitudeText,
|
||||
CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, FontSize, Foreground, pixelsPerDip);
|
||||
var typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
|
||||
var pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip;
|
||||
|
||||
var lonText = new FormattedText(label.LongitudeText,
|
||||
CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, FontSize, Foreground, pixelsPerDip);
|
||||
foreach (var label in labels)
|
||||
{
|
||||
var latText = new FormattedText(label.LatitudeText,
|
||||
CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, FontSize, Foreground, pixelsPerDip);
|
||||
|
||||
var x = label.Position.X + StrokeThickness / 2d + 2d;
|
||||
var y1 = label.Position.Y - StrokeThickness / 2d - latText.Height;
|
||||
var y2 = label.Position.Y + StrokeThickness / 2d;
|
||||
var lonText = new FormattedText(label.LongitudeText,
|
||||
CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, FontSize, Foreground, pixelsPerDip);
|
||||
|
||||
drawingContext.PushTransform(new RotateTransform(label.Rotation, label.Position.X, label.Position.Y));
|
||||
drawingContext.DrawText(latText, new Point(x, y1));
|
||||
drawingContext.DrawText(lonText, new Point(x, y2));
|
||||
drawingContext.Pop();
|
||||
var x = label.X + StrokeThickness / 2d + 2d;
|
||||
var y1 = label.Y - StrokeThickness / 2d - latText.Height;
|
||||
var y2 = label.Y + StrokeThickness / 2d;
|
||||
|
||||
drawingContext.PushTransform(new RotateTransform(label.Rotation, label.X, label.Y));
|
||||
drawingContext.DrawText(latText, new Point(x, y1));
|
||||
drawingContext.DrawText(lonText, new Point(x, y2));
|
||||
drawingContext.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PathFigure CreatePolylineFigure(ICollection<Point> points)
|
||||
private static PathFigure CreatePolylineFigure(IEnumerable<Point> points)
|
||||
{
|
||||
var figure = new PathFigure
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,21 +28,7 @@ namespace MapControl
|
|||
|
||||
protected override void OnViewportChanged(ViewportChangedEventArgs e)
|
||||
{
|
||||
var labels = new List<Label>();
|
||||
var pathFigures = ((PathGeometry)path.Data).Figures;
|
||||
|
||||
pathFigures.Clear();
|
||||
|
||||
SetLineDistance();
|
||||
|
||||
if (ParentMap.MapProjection.Type <= MapProjectionType.NormalCylindrical)
|
||||
{
|
||||
DrawCylindricalGraticule(pathFigures, labels);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawGraticule(pathFigures, labels);
|
||||
}
|
||||
var labels = DrawGraticule(((PathGeometry)path.Data).Figures);
|
||||
|
||||
if (Children.Count == 0)
|
||||
{
|
||||
|
|
@ -89,7 +75,7 @@ namespace MapControl
|
|||
|
||||
matrix.Translate(StrokeThickness / 2d + 2d, -textBlock.DesiredSize.Height / 2d);
|
||||
matrix.Rotate(label.Rotation);
|
||||
matrix.Translate(label.Position.X, label.Position.Y);
|
||||
matrix.Translate(label.X, label.Y);
|
||||
|
||||
((MatrixTransform)textBlock.RenderTransform).Matrix = matrix;
|
||||
|
||||
|
|
@ -104,7 +90,7 @@ namespace MapControl
|
|||
base.OnViewportChanged(e);
|
||||
}
|
||||
|
||||
private static PathFigure CreatePolylineFigure(ICollection<Point> points)
|
||||
private static PathFigure CreatePolylineFigure(IEnumerable<Point> points)
|
||||
{
|
||||
var figure = new PathFigure
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue