|
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text;
//[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.Maui.Graphics.Tests")]
namespace Microsoft.Maui.Graphics
{
static class Matrix3x2Extensions
{
public static bool IsZero(this in Matrix3x2 matrix)
{
if (matrix.M11 != 0)
return false;
if (matrix.M12 != 0)
return false;
if (matrix.M21 != 0)
return false;
if (matrix.M22 != 0)
return false;
if (matrix.M31 != 0)
return false;
if (matrix.M32 != 0)
return false;
return true;
}
public static bool IsFinite(this in Matrix3x2 matrix)
{
bool result = true;
#if NETSTANDARD2_0 || TIZEN40
result &= !(float.IsNaN(matrix.M11) || float.IsInfinity(matrix.M11));
result &= !(float.IsNaN(matrix.M12) || float.IsInfinity(matrix.M12));
result &= !(float.IsNaN(matrix.M21) || float.IsInfinity(matrix.M21));
result &= !(float.IsNaN(matrix.M22) || float.IsInfinity(matrix.M22));
result &= !(float.IsNaN(matrix.M31) || float.IsInfinity(matrix.M31));
result &= !(float.IsNaN(matrix.M32) || float.IsInfinity(matrix.M32));
#else
result &= float.IsFinite(matrix.M11);
result &= float.IsFinite(matrix.M12);
result &= float.IsFinite(matrix.M21);
result &= float.IsFinite(matrix.M22);
result &= float.IsFinite(matrix.M31);
result &= float.IsFinite(matrix.M32);
#endif
return result;
}
public static Vector2 GetScale(this in Matrix3x2 matrix)
{
var sx = matrix.M12 == 0 ? Math.Abs(matrix.M11) : new Vector2(matrix.M11, matrix.M12).Length();
var sy = matrix.M21 == 0 ? Math.Abs(matrix.M22) : new Vector2(matrix.M21, matrix.M22).Length();
if (matrix.GetDeterminant() < 0)
sy = -sy;
return new Vector2(sx, sy);
}
public static float GetRotation(this in Matrix3x2 matrix)
{
return MathF.Atan2(matrix.M12, matrix.M11);
}
public static Vector2 GetTranslation(this in Matrix3x2 matrix)
{
return matrix.Translation;
}
public static Matrix3x2 WithScale(this Matrix3x2 matrix, Vector2 scale)
{
var sx = matrix.M12 == 0 ? Math.Abs(matrix.M11) : new Vector2(matrix.M11, matrix.M12).Length();
var sy = matrix.M21 == 0 ? Math.Abs(matrix.M22) : new Vector2(matrix.M21, matrix.M22).Length();
// if (matrix.GetDeterminant() < 0) sy = -sy;
scale /= new Vector2(sx, sy);
matrix.M11 *= scale.X;
matrix.M12 *= scale.X;
matrix.M21 *= scale.Y;
matrix.M22 *= scale.Y;
return matrix;
// var t = matrix.Translation;
// var r = matrix.GetRotation();
// return CreateMatrix3x2(scale, r, t);
}
public static Matrix3x2 WithoutScale(this in Matrix3x2 matrix)
{
return matrix.WithScale(Vector2.One);
}
public static Matrix3x2 WithRotation(this in Matrix3x2 matrix, float radians)
{
var t = matrix.Translation;
var s = matrix.GetScale();
return CreateMatrix3x2(s, radians, t);
}
public static Matrix3x2 WithoutRotation(this in Matrix3x2 matrix)
{
var t = matrix.Translation;
var s = matrix.GetScale();
return CreateMatrix3x2(s, 0, t);
}
public static Matrix3x2 WithTranslation(this Matrix3x2 matrix, Vector2 translation)
{
matrix.Translation = translation;
return matrix;
}
/// <summary>
/// Creates a matrix from an SRT.
/// </summary>
/// <param name="scale">The scale</param>
/// <param name="rotation">The rotation, in radians</param>
/// <param name="translation">the translation</param>
/// <returns>A Matrix3x2</returns>
/// <remarks>
/// This is equivalent to:<br/>
/// <c>
/// m = Matrix3x2.CreateScale(scale)<br/>
/// m *= Matri3x2.CreateRotation(rotation)<br/>
/// m *= Matri3x2.CreateTranslation(translation)<br/>
/// </c>
/// </remarks>
internal static Matrix3x2 CreateMatrix3x2(Vector2 scale, float rotation, Vector2 translation)
{
var m = Matrix3x2.CreateRotation(rotation);
m.M11 *= scale.X;
m.M12 *= scale.X;
m.M21 *= scale.Y;
m.M22 *= scale.Y;
m.M31 = translation.X;
m.M32 = translation.Y;
return m;
}
public static float GetLengthScale(this in Matrix3x2 matrix)
{
var determinant = matrix.GetDeterminant();
var areaScale = MathF.Abs(determinant);
return MathF.Sqrt(areaScale);
}
public static void CopyTo(this in Matrix3x2 matrix, float[] dst, int offset = 0, int count = 6)
{
count = Math.Min(dst.Length, count);
dst[offset + 0] = matrix.M11;
dst[offset + 1] = matrix.M12;
dst[offset + 2] = matrix.M21;
dst[offset + 3] = matrix.M22;
if (count > 4)
{
dst[offset + 4] = matrix.M31;
dst[offset + 5] = matrix.M32;
}
}
public static void DeconstructScales(this in Matrix3x2 value, out float scale, out float scalex, out float scaley)
{
var det = value.GetDeterminant();
scale = MathF.Sqrt(MathF.Abs(det));
scalex = value.M12 == 0 ? MathF.Abs(value.M11) : new Vector2(value.M11, value.M12).Length();
scaley = value.M21 == 0 ? MathF.Abs(value.M22) : new Vector2(value.M21, value.M22).Length();
if (det < 0)
scaley = -scaley;
}
}
}
|