XAML-Map-Control/MapControl/Shared/Matrix.cs

109 lines
3.4 KiB
C#
Raw Normal View History

2025-02-27 18:46:32 +01:00
using System;
2024-05-22 11:25:32 +02:00
#if UWP
2026-01-06 08:07:25 +01:00
using FrameworkMatrix = Windows.UI.Xaml.Media.Matrix;
2026-01-05 21:27:00 +01:00
#elif WINUI
2026-01-06 08:07:25 +01:00
using FrameworkMatrix = Microsoft.UI.Xaml.Media.Matrix;
2026-01-05 21:27:00 +01:00
#elif AVALONIA
using Avalonia;
2026-01-06 08:07:25 +01:00
using FrameworkMatrix = Avalonia.Matrix;
2021-06-14 21:41:37 +02:00
#endif
namespace MapControl
{
2019-10-25 19:56:23 +02:00
/// <summary>
2026-01-06 08:07:25 +01:00
/// Replaces Windows.UI.Xaml.Media.Matrix, Microsoft.UI.Xaml.Media.Matrix and Avalonia.Matrix
/// to expose Translate, Rotate and Invert methods.
2019-10-25 19:56:23 +02:00
/// </summary>
public struct Matrix(double m11, double m12, double m21, double m22, double offsetX, double offsetY)
{
public double M11 { get; private set; } = m11;
public double M12 { get; private set; } = m12;
public double M21 { get; private set; } = m21;
public double M22 { get; private set; } = m22;
public double OffsetX { get; private set; } = offsetX;
public double OffsetY { get; private set; } = offsetY;
2022-12-01 23:01:06 +01:00
2026-01-06 08:07:25 +01:00
public static implicit operator Matrix(FrameworkMatrix m)
2018-03-08 07:48:41 +01:00
{
2026-01-05 21:27:00 +01:00
#if AVALONIA
return new Matrix(m.M11, m.M12, m.M21, m.M22, m.M31, m.M32);
#else
return new Matrix(m.M11, m.M12, m.M21, m.M22, m.OffsetX, m.OffsetY);
#endif
2022-12-04 20:10:00 +01:00
}
2026-01-06 08:07:25 +01:00
public static implicit operator FrameworkMatrix(Matrix m)
2022-12-04 20:10:00 +01:00
{
2026-01-06 08:07:25 +01:00
return new FrameworkMatrix(m.M11, m.M12, m.M21, m.M22, m.OffsetX, m.OffsetY);
2018-03-08 07:48:41 +01:00
}
2025-12-31 10:57:27 +01:00
public readonly Point Transform(Point p)
{
2022-12-04 20:10:00 +01:00
return new Point(
M11 * p.X + M21 * p.Y + OffsetX,
M12 * p.X + M22 * p.Y + OffsetY);
}
public void Translate(double x, double y)
{
OffsetX += x;
OffsetY += y;
}
public void Rotate(double angle)
{
if (angle != 0d)
{
2026-01-05 21:27:00 +01:00
var cos = Math.Cos(angle * Math.PI / 180d);
var sin = Math.Sin(angle * Math.PI / 180d);
2022-12-03 20:55:17 +01:00
2026-01-05 21:27:00 +01:00
// equivalent to Multiply(new Matrix(cos, sin, -sin, cos, 0d, 0d));
//
SetMatrix(
cos * M11 - sin * M12,
sin * M11 + cos * M12,
cos * M21 - sin * M22,
sin * M21 + cos * M22,
cos * OffsetX - sin * OffsetY,
sin * OffsetX + cos * OffsetY);
}
}
public void Invert()
{
var invDet = 1d / (M11 * M22 - M12 * M21);
if (double.IsInfinity(invDet))
{
2018-08-25 18:50:52 +02:00
throw new InvalidOperationException("Matrix is not invertible.");
}
SetMatrix(
2018-03-07 22:19:16 +01:00
invDet * M22, invDet * -M12, invDet * -M21, invDet * M11,
invDet * (M21 * OffsetY - M22 * OffsetX),
invDet * (M12 * OffsetX - M11 * OffsetY));
}
2022-12-03 20:55:17 +01:00
public void Multiply(Matrix m)
{
SetMatrix(
M11 * m.M11 + M12 * m.M21,
M11 * m.M12 + M12 * m.M22,
M21 * m.M11 + M22 * m.M21,
M21 * m.M12 + M22 * m.M22,
OffsetX * m.M11 + OffsetY * m.M21 + m.OffsetX,
OffsetX * m.M12 + OffsetY * m.M22 + m.OffsetY);
}
private void SetMatrix(double m11, double m12, double m21, double m22, double offsetX, double offsetY)
{
M11 = m11;
M12 = m12;
M21 = m21;
M22 = m22;
OffsetX = offsetX;
OffsetY = offsetY;
}
}
}