//
// 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 };
}
}