mirror of https://github.com/SixLabors/ImageSharp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1015 lines
36 KiB
1015 lines
36 KiB
// <copyright file="SizeTests.cs" company="Six Labors">
|
|
// Copyright (c) Six Labors and contributors.
|
|
// Licensed under the Apache License, Version 2.0.
|
|
// </copyright>
|
|
|
|
namespace SixLabors.Primitives.Tests
|
|
{
|
|
using System.Globalization;
|
|
using System.Numerics;
|
|
using Xunit;
|
|
|
|
/// <summary>
|
|
/// Tests the <see cref="Matrix"/> struct.
|
|
/// </summary>
|
|
public class MatrixTests
|
|
{
|
|
|
|
[Fact]
|
|
public void ImplicitCastMatrixToMatrix3x2()
|
|
{
|
|
Matrix matrix = new Matrix(1, 2, 3, 4, 5, 6);
|
|
|
|
Matrix3x2 convertedMatrix = matrix;
|
|
Assert.Equal(1, convertedMatrix.M11);
|
|
Assert.Equal(2, convertedMatrix.M12);
|
|
Assert.Equal(3, convertedMatrix.M21);
|
|
Assert.Equal(4, convertedMatrix.M22);
|
|
Assert.Equal(5, convertedMatrix.M31);
|
|
Assert.Equal(6, convertedMatrix.M32);
|
|
}
|
|
|
|
[Fact]
|
|
public void ImplicitCastMatrix3x2ToMatrix()
|
|
{
|
|
Matrix3x2 matrix = new Matrix3x2(1, 2, 3, 4, 5, 6);
|
|
|
|
Matrix convertedMatrix = matrix;
|
|
Assert.Equal(1, convertedMatrix.M11);
|
|
Assert.Equal(2, convertedMatrix.M12);
|
|
Assert.Equal(3, convertedMatrix.M21);
|
|
Assert.Equal(4, convertedMatrix.M22);
|
|
Assert.Equal(5, convertedMatrix.M31);
|
|
Assert.Equal(6, convertedMatrix.M32);
|
|
}
|
|
|
|
/// matrix test mostly tken directly from CoreFX
|
|
///
|
|
static Matrix GenerateMatrixNumberFrom1To6()
|
|
{
|
|
Matrix a = new Matrix();
|
|
a.M11 = 1.0f;
|
|
a.M12 = 2.0f;
|
|
a.M21 = 3.0f;
|
|
a.M22 = 4.0f;
|
|
a.M31 = 5.0f;
|
|
a.M32 = 6.0f;
|
|
return a;
|
|
}
|
|
|
|
static Matrix GenerateTestMatrix()
|
|
{
|
|
Matrix m = Matrix.CreateRotation(MathF.ToRadians(30.0f));
|
|
m.Translation = new Vector2(111.0f, 222.0f);
|
|
return m;
|
|
}
|
|
|
|
// A test for Identity
|
|
[Fact]
|
|
public void MatrixIdentityTest()
|
|
{
|
|
Matrix val = new Matrix();
|
|
val.M11 = val.M22 = 1.0f;
|
|
|
|
Assert.True(ApproximateFloatComparer.Equal(val, Matrix.Identity), "Matrix.Indentity was not set correctly.");
|
|
}
|
|
|
|
// A test for Determinant
|
|
[Fact]
|
|
public void MatrixDeterminantTest()
|
|
{
|
|
Matrix target = Matrix.CreateRotation(MathF.ToRadians(30.0f));
|
|
|
|
float val = 1.0f;
|
|
float det = target.GetDeterminant();
|
|
|
|
Assert.True(ApproximateFloatComparer.Equal(val, det), "Matrix.Determinant was not set correctly.");
|
|
}
|
|
|
|
// A test for Determinant
|
|
// Determinant test |A| = 1 / |A'|
|
|
[Fact]
|
|
public void MatrixDeterminantTest1()
|
|
{
|
|
Matrix a = new Matrix();
|
|
a.M11 = 5.0f;
|
|
a.M12 = 2.0f;
|
|
a.M21 = 12.0f;
|
|
a.M22 = 6.8f;
|
|
a.M31 = 6.5f;
|
|
a.M32 = 1.0f;
|
|
Matrix i;
|
|
Assert.True(Matrix.Invert(a, out i));
|
|
|
|
float detA = a.GetDeterminant();
|
|
float detI = i.GetDeterminant();
|
|
float t = 1.0f / detI;
|
|
|
|
// only accurate to 3 precision
|
|
Assert.True(System.Math.Abs(detA - t) < 1e-3, "Matrix.Determinant was not set correctly.");
|
|
|
|
// sanity check against 4x4 version
|
|
Assert.Equal(new Matrix4x4(a).GetDeterminant(), detA);
|
|
Assert.Equal(new Matrix4x4(i).GetDeterminant(), detI);
|
|
}
|
|
|
|
// A test for Invert (Matrix)
|
|
[Fact]
|
|
public void MatrixInvertTest()
|
|
{
|
|
Matrix mtx = Matrix.CreateRotation(MathF.ToRadians(30.0f));
|
|
|
|
Matrix expected = new Matrix();
|
|
expected.M11 = 0.8660254f;
|
|
expected.M12 = -0.5f;
|
|
|
|
expected.M21 = 0.5f;
|
|
expected.M22 = 0.8660254f;
|
|
|
|
expected.M31 = 0;
|
|
expected.M32 = 0;
|
|
|
|
Matrix actual;
|
|
|
|
Assert.True(Matrix.Invert(mtx, out actual));
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual), "Matrix.Invert did not return the expected value.");
|
|
|
|
Matrix i = mtx * actual;
|
|
Assert.True(ApproximateFloatComparer.Equal(i, Matrix.Identity), "Matrix.Invert did not return the expected value.");
|
|
}
|
|
|
|
// A test for Invert (Matrix)
|
|
[Fact]
|
|
public void MatrixInvertIdentityTest()
|
|
{
|
|
Matrix mtx = Matrix.Identity;
|
|
|
|
Matrix actual;
|
|
Assert.True(Matrix.Invert(mtx, out actual));
|
|
|
|
Assert.True(ApproximateFloatComparer.Equal(actual, Matrix.Identity));
|
|
}
|
|
|
|
// A test for Invert (Matrix)
|
|
[Fact]
|
|
public void MatrixInvertTranslationTest()
|
|
{
|
|
Matrix mtx = Matrix.CreateTranslation(23, 42);
|
|
|
|
Matrix actual;
|
|
Assert.True(Matrix.Invert(mtx, out actual));
|
|
|
|
Matrix i = mtx * actual;
|
|
Assert.True(ApproximateFloatComparer.Equal(i, Matrix.Identity));
|
|
}
|
|
|
|
// A test for Invert (Matrix)
|
|
[Fact]
|
|
public void MatrixInvertRotationTest()
|
|
{
|
|
Matrix mtx = Matrix.CreateRotation(2);
|
|
|
|
Matrix actual;
|
|
Assert.True(Matrix.Invert(mtx, out actual));
|
|
|
|
Matrix i = mtx * actual;
|
|
Assert.True(ApproximateFloatComparer.Equal(i, Matrix.Identity));
|
|
}
|
|
|
|
// A test for Invert (Matrix)
|
|
[Fact]
|
|
public void MatrixInvertScaleTest()
|
|
{
|
|
Matrix mtx = Matrix.CreateScale(23, -42);
|
|
|
|
Matrix actual;
|
|
Assert.True(Matrix.Invert(mtx, out actual));
|
|
|
|
Matrix i = mtx * actual;
|
|
Assert.True(ApproximateFloatComparer.Equal(i, Matrix.Identity));
|
|
}
|
|
|
|
// A test for Invert (Matrix)
|
|
[Fact]
|
|
public void MatrixInvertAffineTest()
|
|
{
|
|
Matrix mtx = Matrix.CreateRotation(2) *
|
|
Matrix.CreateScale(23, -42) *
|
|
Matrix.CreateTranslation(17, 53);
|
|
|
|
Matrix actual;
|
|
Assert.True(Matrix.Invert(mtx, out actual));
|
|
|
|
Matrix i = mtx * actual;
|
|
Assert.True(ApproximateFloatComparer.Equal(i, Matrix.Identity));
|
|
}
|
|
|
|
// A test for CreateRotation (float)
|
|
[Fact]
|
|
public void MatrixCreateRotationTest()
|
|
{
|
|
float radians = MathF.ToRadians(50.0f);
|
|
|
|
Matrix expected = new Matrix();
|
|
expected.M11 = 0.642787635f;
|
|
expected.M12 = 0.766044438f;
|
|
expected.M21 = -0.766044438f;
|
|
expected.M22 = 0.642787635f;
|
|
|
|
Matrix actual;
|
|
actual = Matrix.CreateRotation(radians);
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual), "Matrix.CreateRotation did not return the expected value.");
|
|
}
|
|
|
|
// A test for CreateRotation (float, Vector2f)
|
|
[Fact]
|
|
public void MatrixCreateRotationCenterTest()
|
|
{
|
|
float radians = MathF.ToRadians(30.0f);
|
|
Vector2 center = new Vector2(23, 42);
|
|
|
|
Matrix rotateAroundZero = Matrix.CreateRotation(radians, Vector2.Zero);
|
|
Matrix rotateAroundZeroExpected = Matrix.CreateRotation(radians);
|
|
Assert.True(ApproximateFloatComparer.Equal(rotateAroundZero, rotateAroundZeroExpected));
|
|
|
|
Matrix rotateAroundCenter = Matrix.CreateRotation(radians, center);
|
|
Matrix rotateAroundCenterExpected = Matrix.CreateTranslation(-center) * Matrix.CreateRotation(radians) * Matrix.CreateTranslation(center);
|
|
Assert.True(ApproximateFloatComparer.Equal(rotateAroundCenter, rotateAroundCenterExpected));
|
|
}
|
|
|
|
// A test for CreateRotation (float)
|
|
[Fact]
|
|
public void MatrixCreateRotationRightAngleTest()
|
|
{
|
|
// 90 degree rotations must be exact!
|
|
Matrix actual = Matrix.CreateRotation(0);
|
|
Assert.Equal(new Matrix(1, 0, 0, 1, 0, 0), actual);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI / 2);
|
|
Assert.Equal(new Matrix(0, 1, -1, 0, 0, 0), actual);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI);
|
|
Assert.Equal(new Matrix(-1, 0, 0, -1, 0, 0), actual);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI * 3 / 2);
|
|
Assert.Equal(new Matrix(0, -1, 1, 0, 0, 0), actual);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI * 2);
|
|
Assert.Equal(new Matrix(1, 0, 0, 1, 0, 0), actual);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI * 5 / 2);
|
|
Assert.Equal(new Matrix(0, 1, -1, 0, 0, 0), actual);
|
|
|
|
actual = Matrix.CreateRotation(-MathF.PI / 2);
|
|
Assert.Equal(new Matrix(0, -1, 1, 0, 0, 0), actual);
|
|
|
|
// But merely close-to-90 rotations should not be excessively clamped.
|
|
float delta = MathF.ToRadians(0.01f);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI + delta);
|
|
Assert.False(ApproximateFloatComparer.Equal(new Matrix(-1, 0, 0, -1, 0, 0), actual));
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI - delta);
|
|
Assert.False(ApproximateFloatComparer.Equal(new Matrix(-1, 0, 0, -1, 0, 0), actual));
|
|
}
|
|
|
|
// A test for CreateRotation (float, Vector2f)
|
|
[Fact]
|
|
public void MatrixCreateRotationRightAngleCenterTest()
|
|
{
|
|
Vector2 center = new Vector2(3, 7);
|
|
|
|
// 90 degree rotations must be exact!
|
|
Matrix actual = Matrix.CreateRotation(0, center);
|
|
Assert.Equal(new Matrix(1, 0, 0, 1, 0, 0), actual);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI / 2, center);
|
|
Assert.Equal(new Matrix(0, 1, -1, 0, 10, 4), actual);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI, center);
|
|
Assert.Equal(new Matrix(-1, 0, 0, -1, 6, 14), actual);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI * 3 / 2, center);
|
|
Assert.Equal(new Matrix(0, -1, 1, 0, -4, 10), actual);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI * 2, center);
|
|
Assert.Equal(new Matrix(1, 0, 0, 1, 0, 0), actual);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI * 5 / 2, center);
|
|
Assert.Equal(new Matrix(0, 1, -1, 0, 10, 4), actual);
|
|
|
|
actual = Matrix.CreateRotation(-MathF.PI / 2, center);
|
|
Assert.Equal(new Matrix(0, -1, 1, 0, -4, 10), actual);
|
|
|
|
// But merely close-to-90 rotations should not be excessively clamped.
|
|
float delta = MathF.ToRadians(0.01f);
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI + delta, center);
|
|
Assert.False(ApproximateFloatComparer.Equal(new Matrix(-1, 0, 0, -1, 6, 14), actual));
|
|
|
|
actual = Matrix.CreateRotation(MathF.PI - delta, center);
|
|
Assert.False(ApproximateFloatComparer.Equal(new Matrix(-1, 0, 0, -1, 6, 14), actual));
|
|
}
|
|
|
|
// A test for Invert (Matrix)
|
|
// Non invertible matrix - determinant is zero - singular matrix
|
|
[Fact]
|
|
public void MatrixInvertTest1()
|
|
{
|
|
Matrix a = new Matrix();
|
|
a.M11 = 0.0f;
|
|
a.M12 = 2.0f;
|
|
a.M21 = 0.0f;
|
|
a.M22 = 4.0f;
|
|
a.M31 = 5.0f;
|
|
a.M32 = 6.0f;
|
|
|
|
float detA = a.GetDeterminant();
|
|
Assert.True(ApproximateFloatComparer.Equal(detA, 0.0f), "Matrix.Invert did not return the expected value.");
|
|
|
|
Matrix actual;
|
|
Assert.False(Matrix.Invert(a, out actual));
|
|
|
|
// all the elements in Actual is NaN
|
|
Assert.True(
|
|
float.IsNaN(actual.M11) && float.IsNaN(actual.M12) &&
|
|
float.IsNaN(actual.M21) && float.IsNaN(actual.M22) &&
|
|
float.IsNaN(actual.M31) && float.IsNaN(actual.M32)
|
|
, "Matrix.Invert did not return the expected value.");
|
|
}
|
|
|
|
// A test for Lerp (Matrix, Matrix, float)
|
|
[Fact]
|
|
public void MatrixLerpTest()
|
|
{
|
|
Matrix a = new Matrix();
|
|
a.M11 = 11.0f;
|
|
a.M12 = 12.0f;
|
|
a.M21 = 21.0f;
|
|
a.M22 = 22.0f;
|
|
a.M31 = 31.0f;
|
|
a.M32 = 32.0f;
|
|
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
|
|
float t = 0.5f;
|
|
|
|
Matrix expected = new Matrix();
|
|
expected.M11 = a.M11 + (b.M11 - a.M11) * t;
|
|
expected.M12 = a.M12 + (b.M12 - a.M12) * t;
|
|
|
|
expected.M21 = a.M21 + (b.M21 - a.M21) * t;
|
|
expected.M22 = a.M22 + (b.M22 - a.M22) * t;
|
|
|
|
expected.M31 = a.M31 + (b.M31 - a.M31) * t;
|
|
expected.M32 = a.M32 + (b.M32 - a.M32) * t;
|
|
|
|
Matrix actual;
|
|
actual = Matrix.Lerp(a, b, t);
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual), "Matrix.Lerp did not return the expected value.");
|
|
}
|
|
|
|
// A test for operator - (Matrix)
|
|
[Fact]
|
|
public void MatrixUnaryNegationTest()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
|
|
Matrix expected = new Matrix();
|
|
expected.M11 = -1.0f;
|
|
expected.M12 = -2.0f;
|
|
expected.M21 = -3.0f;
|
|
expected.M22 = -4.0f;
|
|
expected.M31 = -5.0f;
|
|
expected.M32 = -6.0f;
|
|
|
|
Matrix actual = -a;
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual), "Matrix.operator - did not return the expected value.");
|
|
}
|
|
|
|
// A test for operator - (Matrix, Matrix)
|
|
[Fact]
|
|
public void MatrixSubtractionTest()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
Matrix expected = new Matrix();
|
|
|
|
Matrix actual = a - b;
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual), "Matrix.operator - did not return the expected value.");
|
|
}
|
|
|
|
// A test for operator * (Matrix, Matrix)
|
|
[Fact]
|
|
public void MatrixMultiplyTest1()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
|
|
Matrix expected = new Matrix();
|
|
expected.M11 = a.M11 * b.M11 + a.M12 * b.M21;
|
|
expected.M12 = a.M11 * b.M12 + a.M12 * b.M22;
|
|
|
|
expected.M21 = a.M21 * b.M11 + a.M22 * b.M21;
|
|
expected.M22 = a.M21 * b.M12 + a.M22 * b.M22;
|
|
|
|
expected.M31 = a.M31 * b.M11 + a.M32 * b.M21 + b.M31;
|
|
expected.M32 = a.M31 * b.M12 + a.M32 * b.M22 + b.M32;
|
|
|
|
Matrix actual = a * b;
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual), "Matrix.operator * did not return the expected value.");
|
|
|
|
// Sanity check by comparison with 4x4 multiply.
|
|
a = Matrix.CreateRotation(MathF.ToRadians(30)) * Matrix.CreateTranslation(23, 42);
|
|
b = Matrix.CreateScale(3, 7) * Matrix.CreateTranslation(666, -1);
|
|
|
|
actual = a * b;
|
|
|
|
Matrix4x4 a44 = new Matrix4x4(a);
|
|
Matrix4x4 b44 = new Matrix4x4(b);
|
|
Matrix4x4 expected44 = a44 * b44;
|
|
Matrix4x4 actual44 = new Matrix4x4(actual);
|
|
|
|
Assert.True(ApproximateFloatComparer.Equal(expected44, actual44), "Matrix.operator * did not return the expected value.");
|
|
}
|
|
|
|
// A test for operator * (Matrix, Matrix)
|
|
// Multiply with identity matrix
|
|
[Fact]
|
|
public void MatrixMultiplyTest4()
|
|
{
|
|
Matrix a = new Matrix();
|
|
a.M11 = 1.0f;
|
|
a.M12 = 2.0f;
|
|
a.M21 = 5.0f;
|
|
a.M22 = -6.0f;
|
|
a.M31 = 9.0f;
|
|
a.M32 = 10.0f;
|
|
|
|
Matrix b = new Matrix();
|
|
b = Matrix.Identity;
|
|
|
|
Matrix expected = a;
|
|
Matrix actual = a * b;
|
|
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual), "Matrix.operator * did not return the expected value.");
|
|
}
|
|
|
|
// A test for operator + (Matrix, Matrix)
|
|
[Fact]
|
|
public void MatrixAdditionTest()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
|
|
Matrix expected = new Matrix();
|
|
expected.M11 = a.M11 + b.M11;
|
|
expected.M12 = a.M12 + b.M12;
|
|
expected.M21 = a.M21 + b.M21;
|
|
expected.M22 = a.M22 + b.M22;
|
|
expected.M31 = a.M31 + b.M31;
|
|
expected.M32 = a.M32 + b.M32;
|
|
|
|
Matrix actual;
|
|
|
|
actual = a + b;
|
|
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual), "Matrix.operator + did not return the expected value.");
|
|
}
|
|
|
|
// A test for ToString ()
|
|
[Fact]
|
|
public void MatrixToStringTest()
|
|
{
|
|
Matrix a = new Matrix();
|
|
a.M11 = 11.0f;
|
|
a.M12 = -12.0f;
|
|
a.M21 = 21.0f;
|
|
a.M22 = 22.0f;
|
|
a.M31 = 31.0f;
|
|
a.M32 = 32.0f;
|
|
|
|
string expected = "{ {M11:11 M12:-12} " +
|
|
"{M21:21 M22:22} " +
|
|
"{M31:31 M32:32} }";
|
|
string actual;
|
|
|
|
actual = a.ToString();
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for Add (Matrix, Matrix)
|
|
[Fact]
|
|
public void MatrixAddTest()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
|
|
Matrix expected = new Matrix();
|
|
expected.M11 = a.M11 + b.M11;
|
|
expected.M12 = a.M12 + b.M12;
|
|
expected.M21 = a.M21 + b.M21;
|
|
expected.M22 = a.M22 + b.M22;
|
|
expected.M31 = a.M31 + b.M31;
|
|
expected.M32 = a.M32 + b.M32;
|
|
|
|
Matrix actual;
|
|
|
|
actual = Matrix.Add(a, b);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for Equals (object)
|
|
[Fact]
|
|
public void MatrixEqualsTest()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
|
|
// case 1: compare between same values
|
|
object obj = b;
|
|
|
|
bool expected = true;
|
|
bool actual = a.Equals(obj);
|
|
Assert.Equal(expected, actual);
|
|
|
|
// case 2: compare between different values
|
|
b.M11 = 11.0f;
|
|
obj = b;
|
|
expected = false;
|
|
actual = a.Equals(obj);
|
|
Assert.Equal(expected, actual);
|
|
|
|
// case 3: compare between different types.
|
|
obj = new Vector4();
|
|
expected = false;
|
|
actual = a.Equals(obj);
|
|
Assert.Equal(expected, actual);
|
|
|
|
// case 3: compare against null.
|
|
obj = null;
|
|
expected = false;
|
|
actual = a.Equals(obj);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for GetHashCode ()
|
|
[Fact]
|
|
public void MatrixGetHashCodeTest()
|
|
{
|
|
Matrix target = GenerateMatrixNumberFrom1To6();
|
|
int expected = unchecked(target.M11.GetHashCode() + target.M12.GetHashCode() +
|
|
target.M21.GetHashCode() + target.M22.GetHashCode() +
|
|
target.M31.GetHashCode() + target.M32.GetHashCode());
|
|
int actual;
|
|
|
|
actual = target.GetHashCode();
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for Multiply (Matrix, Matrix)
|
|
[Fact]
|
|
public void MatrixMultiplyTest3()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
|
|
Matrix expected = new Matrix();
|
|
expected.M11 = a.M11 * b.M11 + a.M12 * b.M21;
|
|
expected.M12 = a.M11 * b.M12 + a.M12 * b.M22;
|
|
|
|
expected.M21 = a.M21 * b.M11 + a.M22 * b.M21;
|
|
expected.M22 = a.M21 * b.M12 + a.M22 * b.M22;
|
|
|
|
expected.M31 = a.M31 * b.M11 + a.M32 * b.M21 + b.M31;
|
|
expected.M32 = a.M31 * b.M12 + a.M32 * b.M22 + b.M32;
|
|
Matrix actual;
|
|
actual = Matrix.Multiply(a, b);
|
|
|
|
Assert.Equal(expected, actual);
|
|
|
|
// Sanity check by comparison with 4x4 multiply.
|
|
a = Matrix.CreateRotation(MathF.ToRadians(30)) * Matrix.CreateTranslation(23, 42);
|
|
b = Matrix.CreateScale(3, 7) * Matrix.CreateTranslation(666, -1);
|
|
|
|
actual = Matrix.Multiply(a, b);
|
|
|
|
Matrix4x4 a44 = new Matrix4x4(a);
|
|
Matrix4x4 b44 = new Matrix4x4(b);
|
|
Matrix4x4 expected44 = Matrix4x4.Multiply(a44, b44);
|
|
Matrix4x4 actual44 = new Matrix4x4(actual);
|
|
|
|
Assert.True(ApproximateFloatComparer.Equal(expected44, actual44), "Matrix.Multiply did not return the expected value.");
|
|
}
|
|
|
|
// A test for Multiply (Matrix, float)
|
|
[Fact]
|
|
public void MatrixMultiplyTest5()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix expected = new Matrix(3, 6, 9, 12, 15, 18);
|
|
Matrix actual = Matrix.Multiply(a, 3);
|
|
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for Multiply (Matrix, float)
|
|
[Fact]
|
|
public void MatrixMultiplyTest6()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix expected = new Matrix(3, 6, 9, 12, 15, 18);
|
|
Matrix actual = a * 3;
|
|
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for Negate (Matrix)
|
|
[Fact]
|
|
public void MatrixNegateTest()
|
|
{
|
|
Matrix m = GenerateMatrixNumberFrom1To6();
|
|
|
|
Matrix expected = new Matrix();
|
|
expected.M11 = -1.0f;
|
|
expected.M12 = -2.0f;
|
|
expected.M21 = -3.0f;
|
|
expected.M22 = -4.0f;
|
|
expected.M31 = -5.0f;
|
|
expected.M32 = -6.0f;
|
|
Matrix actual;
|
|
|
|
actual = Matrix.Negate(m);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for operator != (Matrix, Matrix)
|
|
[Fact]
|
|
public void MatrixInequalityTest()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
|
|
// case 1: compare between same values
|
|
bool expected = false;
|
|
bool actual = a != b;
|
|
Assert.Equal(expected, actual);
|
|
|
|
// case 2: compare between different values
|
|
b.M11 = 11.0f;
|
|
expected = true;
|
|
actual = a != b;
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for operator == (Matrix, Matrix)
|
|
[Fact]
|
|
public void MatrixEqualityTest()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
|
|
// case 1: compare between same values
|
|
bool expected = true;
|
|
bool actual = a == b;
|
|
Assert.Equal(expected, actual);
|
|
|
|
// case 2: compare between different values
|
|
b.M11 = 11.0f;
|
|
expected = false;
|
|
actual = a == b;
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for Subtract (Matrix, Matrix)
|
|
[Fact]
|
|
public void MatrixSubtractTest()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
Matrix expected = new Matrix();
|
|
Matrix actual;
|
|
|
|
actual = Matrix.Subtract(a, b);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for CreateScale (Vector2f)
|
|
[Fact]
|
|
public void MatrixCreateScaleTest1()
|
|
{
|
|
SizeF scales = new SizeF(2.0f, 3.0f);
|
|
Matrix expected = new Matrix(
|
|
2.0f, 0.0f,
|
|
0.0f, 3.0f,
|
|
0.0f, 0.0f);
|
|
Matrix actual = Matrix.CreateScale(scales);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for CreateScale (Vector2f, Vector2f)
|
|
[Fact]
|
|
public void MatrixCreateScaleCenterTest1()
|
|
{
|
|
SizeF scale = new SizeF(3, 4);
|
|
PointF center = new PointF(23, 42);
|
|
|
|
Matrix scaleAroundZero = Matrix.CreateScale(scale, PointF.Zero);
|
|
Matrix scaleAroundZeroExpected = Matrix.CreateScale(scale);
|
|
Assert.True(ApproximateFloatComparer.Equal(scaleAroundZero, scaleAroundZeroExpected));
|
|
|
|
Matrix scaleAroundCenter = Matrix.CreateScale(scale, center);
|
|
Matrix scaleAroundCenterExpected = Matrix.CreateTranslation(-center) * Matrix.CreateScale(scale) * Matrix.CreateTranslation(center);
|
|
Assert.True(ApproximateFloatComparer.Equal(scaleAroundCenter, scaleAroundCenterExpected));
|
|
}
|
|
|
|
// A test for CreateScale (float)
|
|
[Fact]
|
|
public void MatrixCreateScaleTest2()
|
|
{
|
|
float scale = 2.0f;
|
|
Matrix expected = new Matrix(
|
|
2.0f, 0.0f,
|
|
0.0f, 2.0f,
|
|
0.0f, 0.0f);
|
|
Matrix actual = Matrix.CreateScale(scale);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for CreateScale (float, Vector2f)
|
|
[Fact]
|
|
public void MatrixCreateScaleCenterTest2()
|
|
{
|
|
float scale = 5;
|
|
PointF center = new PointF(23, 42);
|
|
|
|
Matrix scaleAroundZero = Matrix.CreateScale(scale, PointF.Zero);
|
|
Matrix scaleAroundZeroExpected = Matrix.CreateScale(scale);
|
|
Assert.True(ApproximateFloatComparer.Equal(scaleAroundZero, scaleAroundZeroExpected));
|
|
|
|
Matrix scaleAroundCenter = Matrix.CreateScale(scale, center);
|
|
Matrix scaleAroundCenterExpected = Matrix.CreateTranslation(-center) * Matrix.CreateScale(scale) * Matrix.CreateTranslation(center);
|
|
Assert.True(ApproximateFloatComparer.Equal(scaleAroundCenter, scaleAroundCenterExpected));
|
|
}
|
|
|
|
// A test for CreateScale (float, float)
|
|
[Fact]
|
|
public void MatrixCreateScaleTest3()
|
|
{
|
|
float xScale = 2.0f;
|
|
float yScale = 3.0f;
|
|
Matrix expected = new Matrix(
|
|
2.0f, 0.0f,
|
|
0.0f, 3.0f,
|
|
0.0f, 0.0f);
|
|
Matrix actual = Matrix.CreateScale(xScale, yScale);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for CreateScale (float, float, Vector2f)
|
|
[Fact]
|
|
public void MatrixCreateScaleCenterTest3()
|
|
{
|
|
SizeF scale = new SizeF(3, 4);
|
|
PointF center = new PointF(23, 42);
|
|
|
|
Matrix scaleAroundZero = Matrix.CreateScale(scale.Width, scale.Height, Vector2.Zero);
|
|
Matrix scaleAroundZeroExpected = Matrix.CreateScale(scale.Width, scale.Height);
|
|
Assert.True(ApproximateFloatComparer.Equal(scaleAroundZero, scaleAroundZeroExpected));
|
|
|
|
Matrix scaleAroundCenter = Matrix.CreateScale(scale.Width, scale.Height, center);
|
|
Matrix scaleAroundCenterExpected = Matrix.CreateTranslation(-center) * Matrix.CreateScale(scale.Width, scale.Height) * Matrix.CreateTranslation(center);
|
|
Assert.True(ApproximateFloatComparer.Equal(scaleAroundCenter, scaleAroundCenterExpected));
|
|
}
|
|
|
|
// A test for CreateTranslation (Vector2f)
|
|
[Fact]
|
|
public void MatrixCreateTranslationTest1()
|
|
{
|
|
PointF position = new PointF(2.0f, 3.0f);
|
|
Matrix expected = new Matrix(
|
|
1.0f, 0.0f,
|
|
0.0f, 1.0f,
|
|
2.0f, 3.0f);
|
|
|
|
Matrix actual = Matrix.CreateTranslation(position);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for CreateTranslation (float, float)
|
|
[Fact]
|
|
public void MatrixCreateTranslationTest2()
|
|
{
|
|
float xPosition = 2.0f;
|
|
float yPosition = 3.0f;
|
|
|
|
Matrix expected = new Matrix(
|
|
1.0f, 0.0f,
|
|
0.0f, 1.0f,
|
|
2.0f, 3.0f);
|
|
|
|
Matrix actual = Matrix.CreateTranslation(xPosition, yPosition);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for Translation
|
|
[Fact]
|
|
public void MatrixTranslationTest()
|
|
{
|
|
Matrix a = GenerateTestMatrix();
|
|
Matrix b = a;
|
|
|
|
// Transformed vector that has same semantics of property must be same.
|
|
PointF val = new PointF(a.M31, a.M32);
|
|
Assert.Equal(val, a.Translation);
|
|
|
|
// Set value and get value must be same.
|
|
val = new PointF(1.0f, 2.0f);
|
|
a.Translation = val;
|
|
Assert.Equal(val, a.Translation);
|
|
|
|
// Make sure it only modifies expected value of matrix.
|
|
Assert.True(
|
|
a.M11 == b.M11 && a.M12 == b.M12 &&
|
|
a.M21 == b.M21 && a.M22 == b.M22 &&
|
|
a.M31 != b.M31 && a.M32 != b.M32,
|
|
"Matrix.Translation modified unexpected value of matrix.");
|
|
}
|
|
|
|
// A test for Equals (Matrix)
|
|
[Fact]
|
|
public void MatrixEqualsTest1()
|
|
{
|
|
Matrix a = GenerateMatrixNumberFrom1To6();
|
|
Matrix b = GenerateMatrixNumberFrom1To6();
|
|
|
|
// case 1: compare between same values
|
|
bool expected = true;
|
|
bool actual = a.Equals(b);
|
|
Assert.Equal(expected, actual);
|
|
|
|
// case 2: compare between different values
|
|
b.M11 = 11.0f;
|
|
expected = false;
|
|
actual = a.Equals(b);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for CreateSkew (float, float)
|
|
[Fact]
|
|
public void MatrixCreateSkewIdentityTest()
|
|
{
|
|
Matrix expected = Matrix.Identity;
|
|
Matrix actual = Matrix.CreateSkew(0, 0);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
// A test for CreateSkew (float, float)
|
|
[Fact]
|
|
public void MatrixCreateSkewXTest()
|
|
{
|
|
Matrix expected = new Matrix(1, 0, -0.414213562373095f, 1, 0, 0);
|
|
Matrix actual = Matrix.CreateSkew(-MathF.PI / 8, 0);
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual));
|
|
|
|
expected = new Matrix(1, 0, 0.414213562373095f, 1, 0, 0);
|
|
actual = Matrix.CreateSkew(MathF.PI / 8, 0);
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual));
|
|
|
|
PointF result = PointF.Transform(new PointF(0, 0), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new PointF(0, 0), result));
|
|
|
|
result = PointF.Transform(new Vector2(0, 1), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new PointF(0.414213568f, 1), result));
|
|
result = PointF.Transform(new PointF(0, -1), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new PointF(-0.414213568f, -1), result));
|
|
|
|
result = PointF.Transform(new PointF(3, 10), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new PointF(7.14213568f, 10), result));
|
|
}
|
|
|
|
// A test for CreateSkew (float, float)
|
|
[Fact]
|
|
public void MatrixCreateSkewYTest()
|
|
{
|
|
Matrix expected = new Matrix(1, -0.414213562373095f, 0, 1, 0, 0);
|
|
Matrix actual = Matrix.CreateSkew(0, -MathF.PI / 8);
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual));
|
|
|
|
expected = new Matrix(1, 0.414213562373095f, 0, 1, 0, 0);
|
|
actual = Matrix.CreateSkew(0, MathF.PI / 8);
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual));
|
|
|
|
Vector2 result = Vector2.Transform(new Vector2(0, 0), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new Vector2(0, 0), result));
|
|
|
|
result = Vector2.Transform(new Vector2(1, 0), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new Vector2(1, 0.414213568f), result));
|
|
|
|
result = Vector2.Transform(new Vector2(-1, 0), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new Vector2(-1, -0.414213568f), result));
|
|
|
|
result = Vector2.Transform(new Vector2(10, 3), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new Vector2(10, 7.14213568f), result));
|
|
}
|
|
|
|
// A test for CreateSkew (float, float)
|
|
[Fact]
|
|
public void MatrixCreateSkewXYTest()
|
|
{
|
|
Matrix expected = new Matrix(1, -0.414213562373095f, 1, 1, 0, 0);
|
|
Matrix actual = Matrix.CreateSkew(MathF.PI / 4, -MathF.PI / 8);
|
|
Assert.True(ApproximateFloatComparer.Equal(expected, actual));
|
|
|
|
Vector2 result = Vector2.Transform(new Vector2(0, 0), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new Vector2(0, 0), result));
|
|
|
|
result = Vector2.Transform(new Vector2(1, 0), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new Vector2(1, -0.414213562373095f), result));
|
|
|
|
result = Vector2.Transform(new Vector2(0, 1), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new Vector2(1, 1), result));
|
|
|
|
result = Vector2.Transform(new Vector2(1, 1), actual);
|
|
Assert.True(ApproximateFloatComparer.Equal(new Vector2(2, 0.585786437626905f), result));
|
|
}
|
|
|
|
// A test for CreateSkew (float, float, Vector2f)
|
|
[Fact]
|
|
public void MatrixCreateSkewCenterTest()
|
|
{
|
|
float skewX = 1, skewY = 2;
|
|
Vector2 center = new Vector2(23, 42);
|
|
|
|
Matrix skewAroundZero = Matrix.CreateSkew(skewX, skewY, Vector2.Zero);
|
|
Matrix skewAroundZeroExpected = Matrix.CreateSkew(skewX, skewY);
|
|
Assert.True(ApproximateFloatComparer.Equal(skewAroundZero, skewAroundZeroExpected));
|
|
|
|
Matrix skewAroundCenter = Matrix.CreateSkew(skewX, skewY, center);
|
|
Matrix skewAroundCenterExpected = Matrix.CreateTranslation(-center) * Matrix.CreateSkew(skewX, skewY) * Matrix.CreateTranslation(center);
|
|
Assert.True(ApproximateFloatComparer.Equal(skewAroundCenter, skewAroundCenterExpected));
|
|
}
|
|
|
|
// A test for IsIdentity
|
|
[Fact]
|
|
public void MatrixIsIdentityTest()
|
|
{
|
|
Assert.True(Matrix.Identity.IsIdentity);
|
|
Assert.True(new Matrix(1, 0, 0, 1, 0, 0).IsIdentity);
|
|
Assert.False(new Matrix(0, 0, 0, 1, 0, 0).IsIdentity);
|
|
Assert.False(new Matrix(1, 1, 0, 1, 0, 0).IsIdentity);
|
|
Assert.False(new Matrix(1, 0, 1, 1, 0, 0).IsIdentity);
|
|
Assert.False(new Matrix(1, 0, 0, 0, 0, 0).IsIdentity);
|
|
Assert.False(new Matrix(1, 0, 0, 1, 1, 0).IsIdentity);
|
|
Assert.False(new Matrix(1, 0, 0, 1, 0, 1).IsIdentity);
|
|
}
|
|
|
|
// A test for Matrix comparison involving NaN values
|
|
[Fact]
|
|
public void MatrixEqualsNanTest()
|
|
{
|
|
Matrix a = new Matrix(float.NaN, 0, 0, 0, 0, 0);
|
|
Matrix b = new Matrix(0, float.NaN, 0, 0, 0, 0);
|
|
Matrix c = new Matrix(0, 0, float.NaN, 0, 0, 0);
|
|
Matrix d = new Matrix(0, 0, 0, float.NaN, 0, 0);
|
|
Matrix e = new Matrix(0, 0, 0, 0, float.NaN, 0);
|
|
Matrix f = new Matrix(0, 0, 0, 0, 0, float.NaN);
|
|
|
|
Assert.False(a == new Matrix());
|
|
Assert.False(b == new Matrix());
|
|
Assert.False(c == new Matrix());
|
|
Assert.False(d == new Matrix());
|
|
Assert.False(e == new Matrix());
|
|
Assert.False(f == new Matrix());
|
|
|
|
Assert.True(a != new Matrix());
|
|
Assert.True(b != new Matrix());
|
|
Assert.True(c != new Matrix());
|
|
Assert.True(d != new Matrix());
|
|
Assert.True(e != new Matrix());
|
|
Assert.True(f != new Matrix());
|
|
|
|
Assert.False(a.Equals(new Matrix()));
|
|
Assert.False(b.Equals(new Matrix()));
|
|
Assert.False(c.Equals(new Matrix()));
|
|
Assert.False(d.Equals(new Matrix()));
|
|
Assert.False(e.Equals(new Matrix()));
|
|
Assert.False(f.Equals(new Matrix()));
|
|
|
|
Assert.False(a.IsIdentity);
|
|
Assert.False(b.IsIdentity);
|
|
Assert.False(c.IsIdentity);
|
|
Assert.False(d.IsIdentity);
|
|
Assert.False(e.IsIdentity);
|
|
Assert.False(f.IsIdentity);
|
|
|
|
// Counterintuitive result - IEEE rules for NaN comparison are weird!
|
|
Assert.False(a.Equals(a));
|
|
Assert.False(b.Equals(b));
|
|
Assert.False(c.Equals(c));
|
|
Assert.False(d.Equals(d));
|
|
Assert.False(e.Equals(e));
|
|
Assert.False(f.Equals(f));
|
|
}
|
|
}
|
|
}
|