// // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. // namespace SixLabors.Primitives { using System; using System.Numerics; using System.Runtime.CompilerServices; /// /// A Matrix object for applying matrix transforms to primitives. /// public struct Matrix : IEquatable { private Matrix3x2 backingMatrix; private static readonly Matrix _identity = new Matrix { backingMatrix = Matrix3x2.Identity }; /// /// Returns the multiplicative identity matrix. /// public static Matrix Identity => _identity; /// /// Returns whether the matrix is the identity matrix. /// public bool IsIdentity => this.backingMatrix.IsIdentity; /// /// Gets or sets the translation component of this matrix. /// public Vector2 Translation => this.backingMatrix.Translation; /// /// Constructs a Matrix3x2 from the given components. /// public Matrix(float m11, float m12, float m21, float m22, float m31, float m32) { this.backingMatrix = new Matrix3x2(m11, m12, m21, m22, m31, m32); } /// /// Creates a translation matrix from the given vector. /// /// The translation position. /// A translation matrix. public static Matrix CreateTranslation(PointF position) => Matrix3x2.CreateTranslation(position); /// /// Creates a translation matrix from the given X and Y components. /// /// The X position. /// The Y position. /// A translation matrix. public static Matrix CreateTranslation(float xPosition, float yPosition) => Matrix3x2.CreateTranslation(xPosition, yPosition); /// /// Creates a scale matrix from the given X and Y components. /// /// Value to scale by on the X-axis. /// Value to scale by on the Y-axis. /// A scaling matrix. public static Matrix CreateScale(float xScale, float yScale) => Matrix3x2.CreateScale(xScale, yScale); /// /// Creates a scale matrix that is offset by a given center point. /// /// Value to scale by on the X-axis. /// Value to scale by on the Y-axis. /// The center point. /// A scaling matrix. public static Matrix CreateScale(float xScale, float yScale, PointF centerPoint) => Matrix3x2.CreateScale(xScale, yScale, centerPoint); /// /// Creates a scale matrix from the given vector scale. /// /// The scale to use. /// A scaling matrix. public static Matrix CreateScale(SizeF scales) => Matrix3x2.CreateScale(scales); /// /// Creates a scale matrix from the given vector scale with an offset from the given center point. /// /// The scale to use. /// The center offset. /// A scaling matrix. public static Matrix CreateScale(SizeF scales, PointF centerPoint) => Matrix3x2.CreateScale(scales, centerPoint); /// /// Creates a scale matrix that scales uniformly with the given scale. /// /// The uniform scale to use. /// A scaling matrix. public static Matrix CreateScale(float scale) => Matrix3x2.CreateScale(scale); /// /// Creates a scale matrix that scales uniformly with the given scale with an offset from the given center. /// /// The uniform scale to use. /// The center offset. /// A scaling matrix. public static Matrix CreateScale(float scale, PointF centerPoint) => Matrix3x2.CreateScale(scale, centerPoint); /// /// Creates a skew matrix from the given angles in radians. /// /// The X angle, in radians. /// The Y angle, in radians. /// A skew matrix. public static Matrix CreateSkew(float radiansX, float radiansY) => Matrix3x2.CreateSkew(radiansX, radiansY); /// /// Creates a skew matrix from the given angles in radians. /// /// The X angle, in degrees. /// The Y angle, in degrees. /// A skew matrix. public static Matrix CreateSkewDegrees(float degreesX, float degreesY) => Matrix3x2.CreateSkew(MathF.DegreeToRadian(degreesX), MathF.DegreeToRadian(degreesY)); /// /// Creates a skew matrix from the given angles in radians and a center point. /// /// The X angle, in radians. /// The Y angle, in radians. /// The center point. /// A skew matrix. public static Matrix CreateSkew(float radiansX, float radiansY, PointF centerPoint) => Matrix3x2.CreateSkew(radiansX, radiansY, centerPoint); /// /// Creates a skew matrix from the given angles in radians and a center point. /// /// The X angle, in degrees. /// The Y angle, in degrees. /// The center point. /// A skew matrix. public static Matrix CreateSkewDegrees(float degreesX, float degreesY, PointF centerPoint) => Matrix3x2.CreateSkew(MathF.DegreeToRadian(degreesX), MathF.DegreeToRadian(degreesY), centerPoint); /// /// Creates a rotation matrix using the given rotation in radians. /// /// The amount of rotation, in radians. /// A rotation matrix. public static Matrix CreateRotation(float radians) => System.Numerics.Matrix3x2.CreateRotation(radians); /// /// Creates a rotation matrix using the given rotation in radians. /// /// The amount of rotation, in degrees. /// A rotation matrix. public static Matrix CreateRotationDegrees(float degrees) => System.Numerics.Matrix3x2.CreateRotation(MathF.DegreeToRadian(degrees)); /// /// Creates a rotation matrix using the given rotation in radians and a center point. /// /// The amount of rotation, in radians. /// The center point. /// A rotation matrix. public static Matrix CreateRotation(float radians, PointF centerPoint) => System.Numerics.Matrix3x2.CreateRotation(radians, centerPoint); /// /// Creates a rotation matrix using the given rotation in radians and a center point. /// /// The amount of rotation, in degrees. /// The center point. /// A rotation matrix. public static Matrix CreateRotationDegrees(float degrees, PointF centerPoint) => Matrix3x2.CreateRotation(MathF.DegreeToRadian(degrees), centerPoint); /// /// Calculates the determinant for this matrix. /// The determinant is calculated by expanding the matrix with a third column whose values are (0,0,1). /// /// The determinant. public float GetDeterminant() => this.backingMatrix.GetDeterminant(); /// /// Attempts to invert the given matrix. If the operation succeeds, the inverted matrix is stored in the result parameter. /// /// The source matrix. /// The output matrix. /// True if the operation succeeded, False otherwise. public static bool Invert(Matrix matrix, out Matrix result) { Matrix3x2 m; var b = System.Numerics.Matrix3x2.Invert(matrix.backingMatrix, out m); result = m; return b; } /// /// Linearly interpolates from matrix1 to matrix2, based on the third parameter. /// /// The first source matrix. /// The second source matrix. /// The relative weighting of matrix2. /// The interpolated matrix. public static Matrix Lerp(Matrix matrix1, Matrix matrix2, float amount) => Matrix3x2.Lerp(matrix1.backingMatrix, matrix2.backingMatrix, amount); /// /// Negates the given matrix by multiplying all values by -1. /// /// The source matrix. /// The negated matrix. public static Matrix Negate(Matrix value) => -value.backingMatrix; /// /// Adds each matrix element in value1 with its corresponding element in value2. /// /// The first source matrix. /// The second source matrix. /// The matrix containing the summed values. public static Matrix Add(Matrix value1, Matrix value2) => value1.backingMatrix + value2.backingMatrix; /// /// Subtracts each matrix element in value2 from its corresponding element in value1. /// /// The first source matrix. /// The second source matrix. /// The matrix containing the resulting values. public static Matrix Subtract(Matrix value1, Matrix value2) => value1.backingMatrix - value2.backingMatrix; /// /// Multiplies two matrices together and returns the resulting matrix. /// /// The first source matrix. /// The second source matrix. /// The product matrix. public static Matrix Multiply(Matrix value1, Matrix value2) => value1.backingMatrix * value2.backingMatrix; /// /// Scales all elements in a matrix by the given scalar factor. /// /// The source matrix. /// The scaling value to use. /// The resulting matrix. public static Matrix Multiply(Matrix value1, float value2) => value1.backingMatrix * value2; /// /// Negates the given matrix by multiplying all values by -1. /// /// The source matrix. /// The negated matrix. public static Matrix operator -(Matrix value) => -value.backingMatrix; /// /// Adds each matrix element in value1 with its corresponding element in value2. /// /// The first source matrix. /// The second source matrix. /// The matrix containing the summed values. public static Matrix operator +(Matrix value1, Matrix value2) => value1.backingMatrix + value2.backingMatrix; /// /// Subtracts each matrix element in value2 from its corresponding element in value1. /// /// The first source matrix. /// The second source matrix. /// The matrix containing the resulting values. public static Matrix operator -(Matrix value1, Matrix value2) => value1.backingMatrix - value2.backingMatrix; /// /// Multiplies two matrices together and returns the resulting matrix. /// /// The first source matrix. /// The second source matrix. /// The product matrix. public static Matrix operator *(Matrix value1, Matrix value2) => value1.backingMatrix * value2.backingMatrix; /// /// Scales all elements in a matrix by the given scalar factor. /// /// The source matrix. /// The scaling value to use. /// The resulting matrix. public static Matrix operator *(Matrix value1, float value2) => value1.backingMatrix * value2; /// /// Returns a boolean indicating whether the given matrices are equal. /// /// The first source matrix. /// The second source matrix. /// True if the matrices are equal; False otherwise. public static bool operator ==(Matrix value1, Matrix value2) => value1.backingMatrix == value2.backingMatrix; /// /// Returns a boolean indicating whether the given matrices are not equal. /// /// The first source matrix. /// The second source matrix. /// True if the matrices are not equal; False if they are equal. public static bool operator !=(Matrix value1, Matrix value2) { return value1.backingMatrix != value2.backingMatrix; } /// /// Returns a boolean indicating whether the matrix is equal to the other given matrix. /// /// The other matrix to test equality against. /// True if this matrix is equal to other; False otherwise. public bool Equals(Matrix other) { return this.backingMatrix == other.backingMatrix; } /// /// Returns a boolean indicating whether the given Object is equal to this matrix instance. /// /// The Object to compare against. /// True if the Object is equal to this matrix; False otherwise. public override bool Equals(object obj) { if (obj is Matrix) { return Equals((Matrix)obj); } return false; } /// /// Returns a String representing this matrix instance. /// /// The string representation. public override string ToString() => this.backingMatrix.ToString(); /// /// Returns the hash code for this instance. /// /// The hash code. public override int GetHashCode() => this.backingMatrix.GetHashCode(); /// /// Creates a with the values of the specified . /// /// The matrix. /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Matrix3x2(Matrix matrix) => matrix.backingMatrix; /// /// Creates a with the values of the specified . /// /// The matrix. /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Matrix(Matrix3x2 matrix) => new Matrix { backingMatrix = matrix }; } }